提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
分享最近在学习VueRouter时配置动态路由和权限管理的一点小心得
一、VueRoute是什么?
vue-router是Vue官方推出的路由管理器,主要用于管理URL,实现URL和组件的对应,以及通过URL进行组件之间的切换,从而使构建单页面应用变得更加简单。这篇文章针对vue-router对应的工作原理进行详细讲解。
单页面应用( SPA)的核心思想之一,就是更新视图而不重新请求页面,简单来说,它在加载页面时,不会加载整个页面,只会更新某个指定的容器中的内容。对于大多数单页面应用,都推荐使用官方支持的 vue-route
二、 先配置动态和静态路由
代码如下:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Layout from '@/views/layout/Layout'
import Login from '@/views/login/Login'
import local from '@/utils/local'; // 自己写的存储方法
Vue.use(VueRouter) //使用路由
// 静态路由
const routes = [
// 登录
{
path: '/login',
component: Login,
hide: true // 不是菜单
},
// 布局
{
path: '/',
component: Layout,
redirect: '/home', //重定向
meta: { title: '后台首页' },
children: [
{
path: '/home',
component: () => import('@/views/home/Home')
}
]
},
]
// 公共路由添加
const router = new VueRouter({ routes })
//动态路由
const dynamicRoutes = [
// 订单管理
{
path: '/order',
component: Layout,
redirect: '/order/order-list',
meta: { title: '订单管理', roles: '', icon: 'el-icon-document' },
children: [
{
path: '/order/order-list',
meta: { title: '订单列表', roles: '' },
component: () => import('@/views/order/OrderList')
},
{
path: '/order/order-edit',
meta: { title: '订单编辑', roles: 'super' },
component: () => import('@/views/order/OrderEdit')
},
]
},
// 商品管理
{
path: '/goods',
component: Layout,
redirect: '/goods/goods-list',
meta: { title: '商品管理', roles: '', icon: 'el-icon-s-shop' },
children: [
{
path: '/goods/goods-list',
meta: { title: '商品列表', roles:'super' },
component: () => import('@/views/goods/GoodsList')
},
{
path: '/goods/goods-cate',
meta: { title: '商品分类', roles:'' },
component: () => import('@/views/goods/GoodsCate')
},
{
path: '/goods/goods-add',
meta: { title: '商品添加', roles: '' },
component: () => import('@/views/goods/GoodsAdd')
},
]
},
// 店铺管理
{
path: '/shop',
component: Layout,
redirect: '/shop',
meta: { title: '店铺管理', roles: 'super', icon: 'el-icon-s-shop' },
children: [
{
path: '',
meta: { title: '店铺列表' },
component: () => import('@/views/shop/Shop')
}
]
},
// 账号管理
{
path: '/account',
component: Layout,
redirect: '/account/account-list',
meta: { title: '账号管理', roles: '', icon: 'el-icon-user' },
children: [
{
path: '/account/account-list',
meta: { title: '账号列表', roles: 'super' },
component: () => import('@/views/account/AccountList')
},
{
path: '/account/account-add',
meta: { title: '账号添加', roles: 'super' },
component: () => import('@/views/account/AccountAdd')
},
{
path: '/account/modify-pwd',
meta: { title: '修改密码', roles: '' },
component: () => import('@/views/account/ModifyPassword')
},
{
path: '/account/personal',
meta: { title: '个人中心', roles: '' },
component: () => import('@/views/account/Personal')
},
]
},
// 销售统计
{
path: '/total',
component: Layout,
redirect: '/total/goodstotal',
meta: { title: '销售统计', roles: 'super', icon: 'iconfont icon-total' },
children: [
{ path: '/total/goodstotal', meta: { title: '商品统计' }, component: () => import('@/views/total/GoodsTotal') },
{ path: '/total/ordertotal', meta: { title: '订单统计' }, component: () => import('@/views/total/OrderTotal') }
]
},
// 给所有空白页配置路由
{
path: '*',
meta: { roles: '' },
hide: true,
redirect: '/error404' // 重定向
},
{
path: '/error404',
meta: { roles: '' },
hide: true,
component: () => import('@/views/error/error.vue')
}
]
export default router // 默认导出
其中meta中的roles 是为了判断登录的人所拥有的权限而判断的 我只是简单的判断了普通用户和超级管理员用户 可以写成数组 添加多个权限 并且通过includes判断是否拥有访问该路由的权限
2.计算当前登录用户所拥有的权限可以访问的路由(权限控制)
代码如下:
// 计算路由
export function calcRoutes() {
let rule = local.get('role') // 从本地获取当前登录用户权限
// local.get('role') 等同于 localStorage.getItem('role')
if (!rule) { // 如果没有获取到权限 则不计算路由渲染菜单
return
}
let allRoutes = [] //计算合并后的路由
let menu = [] // 存入本地的数组
// 计算路由
if (rule === 'super') {
// 超级管理员
router.addRoutes(dynamicRoutes) // 可访问路由
allRoutes = [...routes, ...dynamicRoutes] // 计算后合并的路由
// 计算菜单
menu = allRoutes.filter(v => !v.hide) // 需要显示出来的菜单
} else {
// 普通管理员可以访问的菜单和路由
let arr = dynamicRoutes.filter(v => { // 过滤一级路由
if (v.meta.roles.indexOf('super') === -1) { // 如果找到了super 那么代表管理员才能访问 普通用户无法访问
if (v.meta.roles != 'super') { // 如果没有super 证明普通用户可以访问
if (v.children) {v.children = v.children.filter(c=>c.meta.roles !='super')}} //过滤二级路由 若有子级则判断子级是否有super 有则不可访问该路由 反正可访问
return true
}else{
return false
}
})
router.addRoutes(arr) // 可访问路由
allRoutes = [...routes, ...arr] // 计算后合并的路由
// 计算菜单
menu = allRoutes.filter(v => !v.hide) // 需要显示出来的菜单
}
// 存入本地
local.set('menu', menu)
}
calcRoutes() // 每次刷新页面重新计算路由
需要注意的是 计算路由需要的权限在当前用户登录页面的时候就应该存入本地 然后于index.js页面从本地获取 当然也可以直接用query传值
由于vuerouter本身的BUG 所以需要在根页面的创建后周期里再次调用该函数 以保证在登录之后才从本地取得权限
import {calcRoutes} from '@/router/index'; export default { components: {LeftMenu,RightMain}, created(){calcRoutes()} };
最终在根页面渲染菜单时即可根据权限实现动态渲染
总结
动态路由的配置其实就是把所有人都可以访问的公共路由设为静态路由 把需要权限控制渲染的路由给一个标记 通过筛选该标记来获取所有需要权限控制的路由 最终计算该路由所需权限来实现菜单的渲染