路由权限的实现与动态导航的渲染
1. 作用
- 对于管理系统,不同的账号有不同的权限,登录后所看到的内容自然也应该不同。
- 所以这里就要根据账号的角色渲染不同的导航,有些路由就不能访问。
2. 处理路由,形成不同的权限。
1. 拆分路由
- 把路由拆分成不同的模块,每个模块能访问到的路由是不同的,至于超级管理员这种应该能查看所有路由。
- 这里为了简单演示,就分两个,以便日后查看与理解。
| |
| const normalRoutes = [ |
| |
| { path: '/', redirect: '/login' }, |
| { path: '/login', component: () => import('@/views/login/Login.vue') }, |
| |
| { |
| path: '/home', meta: { title: '首页' }, isMenu: true, icon: 'el-icon-s-home', component: () => import('@/views/home/Layerout.vue'), |
| children: [ |
| { path: '', component: () => import('@/views/home/Home.vue') } |
| ] |
| }, |
| |
| |
| { |
| path: '/goods', meta: { title: '商品管理' }, icon: 'el-icon-sell', isMenu: true, component: () => import('@/views/home/Layerout.vue'), redirect: '/goods/list', |
| children: [ |
| { path: '/goods/list', meta: { title: '商品列表' }, isMenu: true, component: () => import('@/views/goods/GoodsList.vue') }, |
| { path: '/goods/add', meta: { title: '商品添加' }, isMenu: true, component: () => import('@/views/goods/GoodsAdd.vue') }, |
| ] |
| }, |
| |
| { |
| path: '/order', meta: { title: '订单管理' }, icon: 'el-icon-document', isMenu: true, component: () => import('@/views/home/Layerout.vue'), |
| children: [ |
| { path: '', component: () => import('@/views/order/Order.vue') } |
| ] |
| }, |
| ] |
| |
| const superRoutes = [ |
| |
| { |
| path: '/account', icon: 'el-icon-user-solid', meta: { title: '账号管理' }, isMenu: true, component: () => import('@/views/home/Layerout.vue'), redirect: '/account/list', |
| children: [ |
| |
| ] |
| }, |
| |
| { |
| path: '/store', icon: 'el-icon-s-shop', meta: { title: '店铺管理' }, isMenu: true, component: () => import('@/views/home/Layerout.vue'), |
| children: [ |
| { path: '', component: () => import('@/views/store/Store.vue') } |
| ] |
| }, |
| ] |
- 上面的注意点
- meta属性的title是用来记录
路径名字的
,以便后面调用。
- isMenu属性是用来判断要不要显示到导航上,后面可以利用这个属性
踢出不用的路由
。
- icon是element图标的名字
2. 封装函数用以返回不同的路由集合
- 函数内从本地读取当前账号角色分类,当然也可以不用本地读取。
| let role = local.get('role') |
- 根据不同账号返回不同路由,
注意这里要暴露出去
,因为导航栏还要使用到这些路由。
| |
| export function showRoute() { |
| let role = local.get('role') |
| |
| if (role === 'super') { |
| return [...normalRoutes, ...superRoutes] |
| |
| } else { |
| return normalRoutes |
| } |
| } |
3. 路由实例化时调用函数
| const router = new VueRouter({ |
| routes: showRoute() |
| }) |
这样就实现了不同类型账号
能够读取不同的路由
。
路由权限就实现了
。
3. 导航的动态渲染
1. 导航栏获取路由数据
- 引入上面暴露的路由函数
| |
| import { showRoute } from "@/router/index.js"; |
- 筛选出拥有自定义属性isMenu的路由
| export default { |
| data() { |
| return { |
| routes: showRoute().filter(v => v.isMenu) |
| }; |
| } |
| }; |
2. 进行渲染
利用这个获取到的数据渲染一级导航。
- 因为v-for和v-if写到同一个标签上编码软件会报错,实际上是可以运行的。所以要用一个template的虚拟标签来,这里的:key可以写到内部,因为他是个虚拟标签。
| <template v-for="(v, i) in routes"></template> |
- 在里面渲染标签,
v-if进行判断v.children.length是不是1
,如果是就渲染一级导航。
| |
| <el-menu-item :index="v.path" :key="i" v-if="v.children.length===1"> |
| <i :class="v.icon"></i> |
| <span slot="title">{{ v.meta.title }}</span> |
| </el-menu-item> |
- 紧接着写
v-else
二级菜单,因为路由里面还有children也要进行遍历与判断,所以还要用到虚拟标签。
- v-for进行遍历,v-if对取出的值进行判断,如果有isMenu就创建他。
| |
| <el-submenu :index="v.path" v-else :key="i"> |
| <template slot="title"> |
| <i :class="v.icon"></i> |
| <span>{{ v.meta.title }}</span> |
| </template> |
| <el-menu-item-group> |
| |
| <template v-for="(n, j) in v.children"> |
| <el-menu-item :index="n.path" v-if="n.meta" :key="j">{{ n.meta.title }}</el-menu-item> |
| </template> |
| </el-menu-item-group> |
| </el-submenu> |
- 这样就利用路由实现了导航的动态渲染。
4. 解决单页应用的一个bug
- 不同账号在同一设备登录可能会查看到不属于自己权限的内容。必须要刷新一次。
- 因为跳转页面的函数是异步的,所以添加await。
| |
| if (res.data.code === 0) { |
| |
| local.set("token", res.data.token); |
| |
| local.set("role", res.data.role); |
| |
| await this.$router.push("/home"); |
| |
| window.location.reload(); |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现