课程名称:基于Vue3最新标准,实现后台前端综合解
课程章节: 第一章
课程讲师:Sunday
课程内容
是以 用户-> 角色 -> 权限 的一种关系
登入时 会获取到这些数据
permission 会拿到 菜单定义时 相对应的一个名称
prints 对应的是 用户按钮的权限
role 是一个数组 你有多少角色 就返回多少角色
动态路由
将进行权限控制的路由分别拆开来写 然后将公共的路由单独放在一个json内
export 输出
在src 文件夹下 设置了 permission.js main.js 需要引入
import router from './router' import store from './store' // 白名单 const whiteList = ['/login'] /** * 路由前置守卫 */ router.beforeEach(async (to, from, next) => { // 存在 token ,进入主页 // if (store.state.user.token) { // 快捷访问 if (store.getters.token) { if (to.path === '/login') { next('/') } else { // 判断用户资料是否获取 // 若不存在用户信息,则需要获取用户信息 if (!store.getters.hasUserInfo) { // 触发获取用户信息的 action,并获取用户当前权限 const { permission } = await store.dispatch('user/getUserInfo') // 处理用户权限,筛选出需要添加的权限 const filterRoutes = await store.dispatch( 'permission/filterRoutes', permission.menus ) // 利用 addRoute 循环添加 filterRoutes.forEach(item => { router.addRoute(item) }) console.log(router) // 添加完动态路由之后,需要在进行一次主动跳转 return next(to.path) } next() } } else { // 没有token的情况下,可以进入白名单 if (whiteList.indexOf(to.path) > -1) { next() } else { next('/login') } } })
router.addRoute(item) 是vue-router 4最新提供的动态路由方法
vuex permission.js
// 专门处理权限路由的模块 import { publicRoutes, privateRoutes } from '@/router' export default { namespaced: true, state: { // 路由表:初始拥有静态路由权限 routes: publicRoutes }, mutations: { /** * 增加路由 */ setRoutes(state, newRoutes) { // 永远在静态路由的基础上增加新路由 state.routes = [...publicRoutes, ...newRoutes] } }, actions: { /** * 根据权限筛选路由 */ filterRoutes(context, menus) { const routes = [] // 路由权限匹配 menus.forEach(key => { // 权限名 与 路由的 name 匹配 routes.push(...privateRoutes.filter(item => item.name === key)) }) // 最后添加 不匹配路由进入 404 routes.push({ path: '/:catchAll(.*)', redirect: '/404' }) context.commit('setRoutes', routes) return routes } } }
将 公共的路由和私有的路由 进行整合 判断 filterRoutes(vuex方法,接口获取的menus的permission.name)
用接口获取的name 做循环判断 是否和 路由定义的name相同 如果有则添加进去
在用户退出时 也需要 router.removeRoute(menu)
/** * 初始化路由表 */ export function resetRouter() { if ( store.getters.userInfo && store.getters.userInfo.permission && store.getters.userInfo.permission.menus ) { const menus = store.getters.userInfo.permission.menus menus.forEach((menu) => { router.removeRoute(menu) }) }
功能受控指令 v-permission="['importUser']"
import store from '@/store' function checkPermission(el, binding) { // 获取绑定的值,此处为权限 const { value } = binding // 获取所有的功能指令 const points = store.getters.userInfo.permission.points // 当传入的指令集为数组时 if (value && value instanceof Array) { // 匹配对应的指令 const hasPermission = points.some(point => { return value.includes(point) }) // 如果无法匹配,则表示当前用户无该指令,那么删除对应的功能按钮 if (!hasPermission) { el.parentNode && el.parentNode.removeChild(el) } } else { // eslint-disabled-next-line throw new Error('v-permission value is ["admin","editor"]') } } export default { // 在绑定元素的父组件被挂载后调用 mounted(el, binding) { checkPermission(el, binding) }, // 在包含组件的 VNode 及其子组件的 VNode 更新后调用 update(el, binding) { checkPermission(el, binding) } }
自定义了一个 v-permission 设置了内容 判断按钮是否显示
app 也需要引入 app.directive('permission', permission)