Vue3项目练习详细步骤(第五部分:用户模块的功能)
顶部导航栏个人信息显示
接口文档
接口请求与绑定
导航栏下拉菜单功能
路由实现
退出登录和路由跳转实现
基本资料修改
页面结构
接口文档
接口请求与绑定
修改头像
页面结构
头像回显
头像上传
接口文档
重置密码
页面结构
接口文档
接口请求与绑定
顶部导航栏个人信息显示
在Layout.vue中,页面加载完就发送请求,获取个人信息展示,并存储到pinia中,因为将来在个人中心中修改信息的时候还需要使用 。
接口文档
接口请求与绑定
在stores目录下新建userInfo.js并定义Store用于将数据存储到pinia中
import { defineStore } from "pinia"
import {ref} from 'vue'export const useUserInfoStore = defineStore('userInfo',()=>{//1.定义用户信息const info = ref({})//2.定义修改用户信息的方法const setInfo = (newInfo)=>{info.value = newInfo}//3.定义清空用户信息的方法const removeInfo = ()=>{info.value={}}return{info,setInfo,removeInfo}
},{persist:true
})
在user.js中提供获取个人信息的函数
//获取个人信息
export const userInfoGetService = ()=>{return request.get('/user/userInfo');
}
在Layout.vue中获取个人信息,并存储到pinia中
//导入接口函数
import {userInfoGetService} from '@/api/user.js'
//导入pinia
import {useUserInfoStore} from '@/stores/userInfo.js'
const userInfoStore = useUserInfoStore();
import {ref} from 'vue'//获取个人信息
const getUserInf = async ()=>{let result = await userInfoGetService();if(result.code === 0){//成功//存储piniauserInfoStore.info =result.data;}else{//失败alert('获取信息失败')}
}getUserInf()
Layout.vue的顶部导航栏中,绑定展示昵称和头像
<div>用户:<strong>{{ userInfoStore.info.nickname ? userInfoStore.info.nickname : userInfoStore.info.usrename }}</strong></div><el-avatar :src="userInfoStore.info.userPic ? userInfoStore.info.userPic : avatar" />
保存后刷新页面可以看到用户名称和头像正常显示
导航栏下拉菜单功能
在el-dropdown中有四个子条目
- 基本资料
- 更换头像
- 重置密码
- 退出登录
其中其三个起到路由功能,跟左侧菜单中【个人中心】下面的二级菜单是同样的功能,退出登录需要删除本地pinia中存储的token以及userInfo
路由实现
在el-dropdown标签上绑定command事件,当有条目被点击后,会触发这个事件
<el-dropdown placement="bottom-end" @command="handleCommand">
在el-dropdown-item标签上添加command属性,属性值和路由表中/user/xxx保持一致
<el-dropdown-item command="info" :icon="User">基本资料</el-dropdown-item>
<el-dropdown-item command="avatar" :icon="Crop">更换头像</el-dropdown-item>
<el-dropdown-item command="password" :icon="EditPen">重置密码</el-dropdown-item>
<el-dropdown-item command="logout" :icon="SwitchButton">退出登录</el-dropdown-item>
退出登录和路由跳转实现
定义并编写handleCommand函数
import {useRouter} from 'vue-router'
const router = useRouter();
import {ElMessage,ElMessageBox} from 'element-plus'
import { useTokenStore } from '@/stores/token.js'
const tokenStore = useTokenStore()
const handleCommand = (command) => {if (command === 'logout') {//退出登录ElMessageBox.confirm('是否退出登录','提示',{confirmButtonText: '确认',cancelButtonText: '取消',type: 'warning',}).then(async () => {//用户点击了确认//清空pinia中的token和个人信息userInfoStore.info={}tokenStore.token=''//跳转到登录页router.push('/login')ElMessage.success('成功退出登录')}).catch(() => {//用户点击了取消ElMessage({type: 'info',message: '取消退出',})})} else {//路由router.push('/user/' + command)}
}
保存后刷新既可以完成跳转和退出登录
基本资料修改
页面结构
在UserInfo.vue文件中完成用户资料修改的页面结构组件
<script setup>
import { ref } from 'vue'
const userInfo = ref({id: 0,username: 'zhangsan',nickname: 'zs',email: 'zs@163.com',
})
const rules = {nickname: [{ required: true, message: '请输入用户昵称', trigger: 'blur' },{pattern: /^\S{2,10}$/,message: '昵称必须是2-10位的非空字符串',trigger: 'blur'}],email: [{ required: true, message: '请输入用户邮箱', trigger: 'blur' },{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' }]
}
</script>
<template><el-card class="page-container"><template #header><div class="header"><span>基本资料</span></div></template><el-row><el-col :span="12"><el-form :model="userInfo" :rules="rules" label-width="100px" size="large"><el-form-item label="登录名称"><el-input v-model="userInfo.username" disabled></el-input></el-form-item><el-form-item label="用户昵称" prop="nickname"><el-input v-model="userInfo.nickname"></el-input></el-form-item><el-form-item label="用户邮箱" prop="email"><el-input v-model="userInfo.email"></el-input></el-form-item><el-form-item><el-button type="primary">提交修改</el-button></el-form-item></el-form></el-col></el-row></el-card>
</template>
个人信息之前已经存储到了pinia中,只需要从pinia中获取个人信息,替换模板数据即可
import { ref } from 'vue'
//导入Store
import { useUserInfoStore } from '@/stores/userInfo.js';
const userInfoStore = useUserInfoStore()
//数据模型
const userInfo = ref({...userInfoStore.info}) //...用于展开可迭代对象 拆出其中的每个元素
接口文档
接口请求与绑定
在src/api/user.js中提供修改基本资料的函数
//修改个人信息
export const userInfoUpdateService = (userInfo)=>{return request.put('/user/update',userInfo)
}
在UserInfo.vue文件中提供updateUserInfo请求函数
//修改用户信息
import {userInfoUpdateService} from '@/api/user.js'
import { ElMessage } from 'element-plus';
const updateUserInfo = async ()=>{let result = await userInfoUpdateService(userInfo.value)ElMessage.success(result.message? result.message:'修改成功')//更新pinia中的数据userInfoStore.info.nickname=userInfo.value.nicknameuserInfoStore.info.email = userInfo.value.email
}
给修改按钮绑定单击事件
<el-button type="primary" @click="updateUserInfo">提交修改</el-button>
保存刷新后能正常完成用户信息的数据回显和更新
修改头像
页面结构
在UserAvatar.vue文件中完成用户资料修改的页面结构组件
<script setup>
import { Plus, Upload } from '@element-plus/icons-vue'
import {ref} from 'vue'
import avatar from '@/assets/default.png'
const uploadRef = ref()//用户头像地址
const imgUrl= avatar</script><template><el-card class="page-container"><template #header><div class="header"><span>更换头像</span></div></template><el-row><el-col :span="12"><el-upload ref="uploadRef"class="avatar-uploader" :show-file-list="false"><img v-if="imgUrl" :src="imgUrl" class="avatar" /><img v-else src="avatar" width="278" /></el-upload><br /><el-button type="primary" :icon="Plus" size="large" @click="uploadRef.$el.querySelector('input').click()">选择图片</el-button><el-button type="success" :icon="Upload" size="large">上传头像</el-button></el-col></el-row></el-card>
</template><style lang="scss" scoped>
.avatar-uploader {:deep() {.avatar {width: 278px;height: 278px;display: block;}.el-upload {border: 1px dashed var(--el-border-color);border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;transition: var(--el-transition-duration-fast);}.el-upload:hover {border-color: var(--el-color-primary);}.el-icon.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 278px;height: 278px;text-align: center;}}
}
</style>
头像回显
从pinia中读取用户的头像数据
//读取用户信息
//导入Store
import {useUserInfoStore} from '@/stores/userInfo.js'
const userInfoStore = useUserInfoStore()
//用户头像地址
const imgUrl=ref(userInfoStore.info.userPic)
img标签上绑定图片地址(三元运输符判断)
<img v-if="imgUrl" :src="imgUrl" class="avatar" />
<img v-else :src="avatar" width="278" />
保存刷新查看头像回显
头像上传
- action: 服务器接口路径
- headers: 设置请求头,需要携带token
- on-success: 上传成功的回调函数
- name: 上传图片的字段名称
为el-upload指定属性值
<el-upload ref="uploadRef"class="avatar-uploader" :show-file-list="false":auto-upload="true"action="/api/upload"name="'file'":headers="{'Authorization':tokenStore.token}":on-success="uploadSuccess">
提供上传成功的回调函数
//导入tokenStore
import {useTokenStore} from '@/stores/token.js'const tokenStore = useTokenStore();
//头像上传成功回调函数
const uploadSuccess = (result)=>{//回显图片imgUrl.value = result.data
}
接口文档
接口请求与绑定
在user.js中提供修改头像的函数
//修改头像
export const userAvatarUpdateService=(avatarUrl)=>{let params = new URLSearchParams();params.append('avatarUrl',avatarUrl)return request.patch('/user/updateAvatar',params)
}
在UserAvatar.vue文件中提供updateAvatar函数,完成头像更新
//调用接口,更新头像url
import {userAvatarUpdateService} from '@/api/user.js'
//导入Element-Plus提示框组件
import {ElMessage} from 'element-plus'
const updateAvatar = async ()=>{let result = await userAvatarUpdateService(imgUrl.value)if(result.code === 0){//成功ElMessage.success(result.message? result.message:'修改成功')//更新pinia中的数据userInfoStore.info.userPic=imgUrl.value}else{ElMessage.error('修改失败')}}
在【上传头像】按钮绑定单击事件
<el-button type="success" :icon="Upload" size="large" @click="updateAvatar">
上传头像
</el-button>
如果是用的网络存储服务器那么到这一步修改头像就完成了!
练习项目后端使用的是本地文件存储,所以没有用到网络url,传入本地文件地址后端会报如下错误
点击上传由于这里练习项目没有网络服务器 数据是上传到本地的所以浏览器会拦截本地文件加载导致不能造成数据回显,但是目录下是有图片成功上传到的。
后续继续完成项目建议修改src中的值为模拟的固定网络图片url地址:https://ts1.cn.mm.bing.net/th/id/R-C.4bdc8f7f0e0201905fe400fb5156b7c7?rik=MVFo1SU7cYgFqg&riu=http%3A%2F%2Fwww.spasvo.com%2Fckfinder%2Fuserfiles%2Fimages%2F2020061536450116.jpg&ehk=r7Pp%2FX3wIOhP%2FcuW0ITLAHeD0sZPNatsyfpC3XWOM0s%3D&risl=&pid=ImgRaw&r=0
如果自己有网络服务器可以使用网络服务器的图片url
重置密码
页面结构
在UserResetPassword.vue文件中完成重置密码的页面的结构组件
<script setup>
import { ref } from 'vue'
const password = ref({
"old_pwd":"",
"new_pwd":"",
"re_pwd":""
})
const rules = {oldPassword: [{ required: true, message: '请输入原密码', trigger: 'blur' },{pattern: /^\S{5,12}$/,message: '密码必须是5-12位的非空字符串',trigger: 'blur'}],newPassword: [{ required: true, message: '请输入新密码', trigger: 'blur' },{pattern: /^\S{5,12}$/,message: '密码必须是5-12位的非空字符串',trigger: 'blur'}],rePassword: [{ required: true, message: '请输入确认新密码', trigger: 'blur' },{pattern: /^\S{5,12}$/,message: '密码必须是5-12位的非空字符串',trigger: 'blur'}]}
</script>
<template><el-card class="page-container"><template #header><div class="header"><span>重置密码</span></div></template><el-row><el-col :span="12"><el-form :model="password" :rules="rules" label-width="100px" size="large"><el-form-item label="原密码" prop="oldPassword"><el-input type="password" placeholder="请输入原密码" show-password v-model="password.old_pwd"></el-input></el-form-item><el-form-item label="新密码" prop="newPassword"><el-input type="password" placeholder="请输入新密码" show-password v-model="password.new_pwd"></el-input></el-form-item><el-form-item label="确认新密码" prop="rePassword"><el-input type="password" placeholder="请输入确认密码" show-password v-model="password.re_pwd"></el-input></el-form-item><el-form-item><el-button type="primary">修改密码</el-button><el-button type="primary">重置</el-button></el-form-item></el-form></el-col></el-row></el-card>
</template>
定义清空数据模型的函数
在重置按钮处绑定清空文本框数据的单击事件
<el-button type="primary" @click="clearData()">重置</el-button>
接口文档
接口请求与绑定
在src/api/user.js中提供重置密码的函数
//重置密码
export const userPasswordUpdateService = (password) => {return request.patch('/user/updatePwd',password)
}
在UserResetPassword.vue文件中提供userPasswordUpdate请求函数
//导入路由
import {useRouter} from 'vue-router'
const router = useRouter();
//导入element提示框组件
import { ElMessage,ElMessageBox } from 'element-plus';
//导入userPasswordUpdateService函数
import {userPasswordUpdateService} from '@/api/user.js'const userPasswordUpdate = async() => {ElMessageBox.confirm('确认是否重置密码,重置之后将退出登录','提示',{confirmButtonText: '确认',cancelButtonText: '取消',type: 'warning',}).then(async () => {//用户点击了确认let result = userPasswordUpdateService(password.value)if(result.code ===0){//成功//跳转到登录页router.push('/login')ElMessage.success(result.message?result.message:'重置成功')ElMessage.success('退出登录')}else{ElMessage.error('操作失败')}}).catch(() => {//用户点击了取消ElMessage({type: 'info',message: '取消重置',})})
}
在修改密码按钮处绑定该函数单击事件
<el-button type="primary" @click="userPasswordUpdate()">修改密码</el-button>
保存后查看效果
项目练习完结
相关文章:

Vue3项目练习详细步骤(第五部分:用户模块的功能)
顶部导航栏个人信息显示 接口文档 接口请求与绑定 导航栏下拉菜单功能 路由实现 退出登录和路由跳转实现 基本资料修改 页面结构 接口文档 接口请求与绑定 修改头像 页面结构 头像回显 头像上传 接口文档 重置密码 页面结构 接口文档 接口请求与绑定 顶部导航…...

测试onlyoffice在线预览文件功能
HTML示例代码 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><title>测试onlyoffice在线预览文件功能</title><script type"text/javascript" src"http://onlyoffice服务器ip:端口/…...
Day57 每日温度 + 下一个更大元素Ⅰ
739 每日温度 题目链接:739.每日温度 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,…...
nuxt3 api如何透传(不引第3方库)
背景: nuxt做为一个vue的服务端渲染框架,本身就具备服务端的功能,理论上可以完整做一个系统功能,包括对数据库等等操作,但更合理的做法是nuxt应该定位只做服务端渲染的事情,更偏向ui层面,而非数据curd,业务逻辑,权限等等偏向服务端的逻辑。本身基于vue的服务端渲染已…...

list常用接口模拟实现
文章目录 一、模拟list类的框架二、函数接口实现1、迭代器接口2、常用删除、插入接口3、常用其他的一些函数接口4、默认成员函数 一、模拟list类的框架 1、使用带哨兵的双向链表实现。 2、链表结点: // List的结点类 template<class T> struct ListNode {Li…...
前端工程化工具系列(三) —— Stylelint(v16.6.1):CSS/SCSS 代码质量工具
Stylelint 是 CSS/SCSS 代码的静态分析工具,用于检查代码中的错误和样式违规。 1. 环境要求 v16 以上的 Stylelint,支持 Node.js 的版本为 v18.12.0。 在命令行中输入以下内容来查看当前系统中 node 的版本。 node -vNode.js 推荐使用 v18.20.3 或者 …...

crossover mac好用吗 CrossOver Mac怎么下载 Mac用crossover损害电脑吗
CrossOver 是一款可以让Mac用户能够自由运行和游戏windows游戏软件的虚拟机类应用,虽然能够虚拟windows但是却并不是一款虚拟机,也不需要重启系统或者启动虚拟机,类似于一种能够让mac系统直接运行windows软件的插件。它以其出色的跨平台兼容性…...
PHP模块pdo_sqlite.so: undefined symbol: sqlite3_column_table_name
安装 php-sqlite3 之后,执行php -m 命令有警告,如下 PHP Warning: PHP Startup: Unable to load dynamic library pdo_sqlite (tried: /usr/lib64/php/modules/pdo_sqlite (/usr/lib64/php/modules/pdo_sqlite: cannot open shared object file: No su…...

卷积神经网络-奥特曼识别
数据集 四种奥特曼图片_数据集-飞桨AI Studio星河社区 (baidu.com) 中间的隐藏层 已经使用参数的空间 Conv2D卷积层 ReLU激活层 MaxPool2D最大池化层 AdaptiveAvgPool2D自适应的平均池化 Linear全链接层 Dropout放置过拟合,随机丢弃神经元 -----------------…...

VB.net进行CAD二次开发(四)
netload不能弹出对话框,参考文献2 参考文献1说明了自定义菜单的问题,用的是cad的系统命令 只要加载了dll,自定义的命令与cad的命令同等地位。 这时,可以将自定义菜单的系统命令替换为自定义命令。 <CommandMethod("Add…...

3步轻松月入过万,APP广告新模式大揭秘!
万万没想到:用这个APP广告模式,月入过万竟然如此简单! 在移动应用开发的世界里,变现一直是一道难题。 许多APP开发者和产品经理为了提高收益、增强用户黏性,不断尝试各种策略。 然而,很多时候,…...

java项目之智能家居系统源码(springboot+vue+mysql)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的智能家居系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 基于Springboot的智能家居系…...
前端 JS 经典:读取文件原始内容
前言:有些时候在工程化开发中,我们需要读取文件里面的原始内容,比如,你有一个文件,后缀名为 .myfile,你需要拿到这个文件里的内容,该怎么处理呢。 在 vue2 中,因为 vue2 使用 vue-c…...

汇编概论和实践
一 汇编第一例 C代码 #include <stdio.h>int main() {printf("Hello, World!\n");return 0; }对应的汇编 .LC0:.string "Hello, World!"main:pushq %rbpmovq %rsp, %rbpleaq .LC0(%rip), %rdicall puts@PLTmovl $0, %eaxpopq %rbpret 二 CPU架构…...

铁塔基站用能监控能效解决方案
截至2023年10月,我国5G基站总数达321.5万个,占全国通信基站总数的28.1%。然而,随着5G基站数量的快速增长,基站的能耗问题也逐渐日益凸显,基站的用电给运营商带来了巨大的电费开支压力,降低5G基站的能耗成为…...

keepalived安装文档
目录 1、安装环境 2、安装keepalived 2.1 上传keepalived安装文件 2.2 解压 2.3 安装keepalived 2.4 加入开机启动: 2.5 配置日志文件 2.6 打开防火墙的通讯地址 1、安装环境 su - root yum -y install kernel-devel* yum -y install openssl-* yum -y …...
Spring Security
Spring Security spring提供的安全框架。主要提供了认证和授权的功能。简单梳理看看。 原理简单说就是Spring Security在基于Servlet应用中,其底层采用了Filter机制实现了对请求的认证,授权和漏洞防御等功能。 DelegatingFilterProxy 我们知道,Filter是Servlet规范里面…...

vue中大屏可视化适配所有屏幕大小
1. 外部盒子 .screenBox {width: 100vw;height: 100vh;background: url("/assets/images/bg.png") no-repeat;background-size: cover; }2.比例盒子 外层盒子css定义 .boxScale {width: 1920px;height: 1080px;background-color: orange;transform-origin: left top;…...

AI大模型探索之路-实战篇12: 构建互动式Agent智能数据分析平台:实现多轮对话控制
系列篇章💥 AI大模型探索之路-实战篇4:深入DB-GPT数据应用开发框架调研 AI大模型探索之路-实战篇5:探索Open Interpreter开放代码解释器调研 AI大模型探索之路-实战篇6:掌握Function Calling的详细流程 AI大模型探索之路-实战篇7…...

深入理解文件系统和日志分析
文件是存储在硬盘上的,硬盘上的最小存储单位是扇区,每个扇区的大小是512字节。 inode:存储元信息(包括文件的属性,权限,创建者,创建日期等等) block:块,连续…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...

DeepSeek越强,Kimi越慌?
被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...
python打卡day49@浙大疏锦行
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 一、通道注意力模块复习 & CBAM实现 import torch import torch.nn as nnclass CBAM(nn.Module):def __init__…...
【Java】Ajax 技术详解
文章目录 1. Filter 过滤器1.1 Filter 概述1.2 Filter 快速入门开发步骤:1.3 Filter 执行流程1.4 Filter 拦截路径配置1.5 过滤器链2. Listener 监听器2.1 Listener 概述2.2 ServletContextListener3. Ajax 技术3.1 Ajax 概述3.2 Ajax 快速入门服务端实现:客户端实现:4. Axi…...