Vue 3 项目实战教程:大事件管理系统(三)——首页框架与头部用户信息实现
1.首页架子搭建
1.1 样式布局
预期布局:
查看 element-ui 官方文档,看Container 布局容器
- el-container 最外层
- el-aside 侧边栏
- el-main 主体内容
- el-footer 底部内容

根据这个模板写的布局
<el-container class="layout-container">
<el-aside width="200px">
放入侧边栏菜单组件
</el-aside>
<el-container>
<el-header>
头部区域:左边一个标题,右边一个下拉菜单
</el-header>
<el-main>
主要内容部:放路由出口
<router-view></router-view>
</el-main>
<el-footer>放入底部文字</el-footer>
</el-container>
</el-container>
首先考虑侧边栏,侧边栏用的
看官方文档菜单
<el-menu
active-text-color="#ffd04b"
background-color="#232323"
:default-active="$route.path"
text-color="#fff"
router
>
<el-menu-item index="/article/channel">
<el-icon><Management /></el-icon>
<span>文章分类</span>
</el-menu-item>
<el-menu-item index="/article/manage">
<el-icon><Promotion /></el-icon>
<span>文章管理</span>
</el-menu-item>
<el-sub-menu index="/user">
<template #title>
<el-icon><UserFilled /></el-icon>
<span>个人中心</span>
</template>
<el-menu-item index="/user/profile">
<el-icon><User /></el-icon>
<span>基本资料</span>
</el-menu-item>
<el-menu-item index="/user/avatar">
<el-icon><Crop /></el-icon>
<span>更换头像</span>
</el-menu-item>
<el-menu-item index="/user/password">
<el-icon><EditPen /></el-icon>
<span>重置密码</span>
</el-menu-item>
</el-sub-menu>
</el-menu>
最外层 配置项讲解
<el-menu
active-text-color="#ffd04b"
background-color="#232323"
:default-active="$route.path"
text-color="#fff"
router
>
| 属性名 | 含义 |
|---|---|
active-text-color |
当前选中项的文字颜色 |
background-color |
菜单整体背景色 |
:default-active |
默认高亮的菜单项,绑定的是 $route.path,即当前页面路径 |
text-color |
普通菜单项的文字颜色 |
router |
启用 Vue Router 模式,点击菜单自动跳转路由 |
普通菜单项(<el-menu-item>)
<el-menu-item index="/article/channel">
<el-icon><Management /></el-icon>
<span>文章分类</span>
</el-menu-item>
index 放一个路由路径 el-icon 放图标 span 里放文字
带有下拉选项的菜单(el-sub-menu)
<el-sub-menu index="/user">
<template #title>
<el-icon><UserFilled /></el-icon>
<span>个人中心</span>
</template>
<el-menu-item index="/user/profile">
<el-icon><User /></el-icon>
<span>基本资料</span>
</el-menu-item>
<el-menu-item index="/user/avatar">
<el-icon><Crop /></el-icon>
<span>更换头像</span>
</el-menu-item>
<el-menu-item index="/user/password">
<el-icon><EditPen /></el-icon>
<span>重置密码</span>
</el-menu-item>
</el-sub-menu>
标题设置通过具名插槽的写法
<template #title>
<el-icon><UserFilled /></el-icon>
<span>个人中心</span>
</template>
下面的每一个子项都用el-menu-item包裹跟上面的一样
question one:
index=“/user/password” 是什么?
index 是 Element Plus 的菜单组件 或 的一个属性,用来标识这个菜单项的唯一标识值,不是浏览器的 index,也不是 Vue 的 index。不一定“必须”这么写成路径 /user/password,但 你必须给它一个唯一的 index 值,否则菜单行为无法区分每项。通过在最外层 el-menu配置router,可以实现路由跳转,它不是 Vue Router 的功能,而是 Element Plus 帮你封装好了
1.2 登入访问拦截
预期:在首页时,如果没有登入,应该拦截登入(没有 token的时候应该拦截登入
登入访问拦截,写在 router/index.js 中

两个参数 to 和 from 的解释:
假设你当前页面是 /login,然后点击跳转到 /article/manage
to.path 就是/article/manage
from.path 就是/login
登入访问拦截=>默认是直接放行的
放回值的几种情况
- undefined/true 直接放行
- false 拦回 from 的地址页面,从哪里来回到哪里去
- 具体路径或路径对象 拦截到对应的地址
- ‘/login’ {name:‘login’}
import { useUserStore } from '@/stores'
//登入访问拦截,默认不写 return 直接放行
router.beforeEach((to)=>{
// 如果没有 token,且访问的是非登入界面,拦截到登录,其他情况正常放行
const useStore=useUserStore()
if(!useStore.token&&to.path!=='/login') return '/login'
})

1.3 右上角用户信息实现
查看接口文档 ,基本的请求封装已经写好了
1.将获取用户的基本信息,写在 api/user.js 中
// 获取用户基本信息
export const userGetInfoService=()=> request.get('/my/userinfo')
2.将拿到的用户信息存在 pinia 中
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { userGetInfoService } from '@/api/user'
export const useUserStore = defineStore(
'big-user',
() => {
const token = ref('') // 定义 token
const setToken = (newToken) => (token.value = newToken) // 设置 token
const removeToken=()=>{token.value=''}
// 定义用户信息
const user=ref({}) //定义一个空的用户信息
const getUser =async()=>{
const res =await userGetInfoService() //请求获取数据
user.value=res.data.data
}
return { token,setToken,removeToken,user,getUser }
},
{
persist: true,
},
)
3.在架子页面中调用拿去用户信息的代码,然后渲染用户信息
import {useUserStore} from '@/stores'
import { onMounted } from 'vue'
const userStore =useUserStore()
//加载阶段访问获取到的用户数据,不写这个钩子函数也可以
onMounted(async () => {
await userStore.getUser() // 等请求完
console.log(userStore.user) // 这时候数据就拿到了
})
cosole.log 结果,注意等创建完成功后打印,才能拿到 console.log 的结果,如果不需要 console.log,也不用写成 await 的那种写法
开始渲染页面
<div>用户:<strong>{{ userStore.user.nickname||userStore.user.username}}</strong></div>
<el-dropdown placement="bottom-end">
<span class="el-dropdown__box">
<el-avatar :src="userStore.user.user_pic||avatar" />
渲染成功
1.4 下拉菜单dropdown实现
<el-dropdown placement="bottom-end">
<span class="el-dropdown__box">
<el-avatar :src="userStore.user.user_pic||avatar" />
<el-icon><CaretBottom /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="profile" :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
>
</el-dropdown-menu>
</template>
</el-dropdown>
解释说明:
el-dropdown
- placement=“bottom-end”:控制下拉菜单展开方向为右下角(靠右展开)。
- #dropdown:这是插槽,表示下拉面板的内容。
- el-dropdown-menu:下拉列表容器。
- el-dropdown-item:每一个选项。
<template #dropdown>是具名插槽的写法,template中间放置下拉菜单中的每一个小项
关于 command,例子如下
command 是 Element Plus(Element-UI 的 Vue 3 版本)提供的标准属性,用于 <el-dropdown-item> 组件。其中 cmd 传入的就是 command 的值,点击事件传入 command
function handleCommand(cmd) {
console.log(cmd) // 打印出 'logout' 或 'profile'
}
<el-dropdown @command="handleCommand">
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
<el-dropdown-item command="profile">基本资料</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
单独定义handleCommand函数
自定义command 函数,点击路由跳转,点击退出登入清除本地信息
LayoutContainer.vue
const router =useRouter()
//自定义 command 函数,编写跳转路由和退出登入
const handleCommand =(key)=>{
// 1.如果key 是退出登入,则清除本地数据(本地数据包含 token 和 user 信息)
// 2.跳转路由
if(key=='logout'){
userStore.removeToken()
userStore.setUser({})
router.push('/login')
}else{
//如果 key 不是退出登入,跳转到相应的路由
router.push(`/article/${key}`)
}
src/stores/modules/user.js
//清除用户数据的函数
const setUser =(obj)=>{
user.value=obj
}
功能测试成功
直接退出登入显得比较随意,应该让用户确认退出
使用组件
将红框内的函数加到下面的代码中,注意使用 async await,等待 await 成功执行并执行,否则不执行
const router =useRouter()
//自定义 command 函数,编写跳转路由和退出登入
const handleCommand =(key)=>{
// 1.如果key 是退出登入,则清除本地数据(本地数据包含 token 和 user 信息)
// 2.跳转路由
if(key=='logout'){
userStore.removeToken()
userStore.setUser({})
router.push('/login')
}else{
//如果 key 不是退出登入,跳转到相应的路由
router.push(`/article/${key}`)
}
const router =useRouter()
//自定义 command 函数,编写跳转路由和退出登入
const handleCommand =async (key)=>{
// 1.如果key 是退出登入,则清除本地数据(本地数据包含 token 和 user 信息)
// 2.跳转路由
await ElMessageBox.confirm(
'你确认要进行退出吗?',
'温馨提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
if(key=='logout'){
userStore.removeToken()
userStore.setUser({})
router.push('/login')
}else{
//如果 key 不是退出登入,跳转到相应的路由
router.push(`/article/${key}`)
}
}

更多推荐



所有评论(0)