🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
>[success] # 简单权限 [结合官方做法](https://router.vuejs.org/guide/advanced/meta.html) ~~~ 1.在做后台管理系统的时候,一定会接触到权限管理,对应的页面会, 根据不同用户的权限进行展示 2.简单权限是根据'iview-admin' 中的方式进行配置,通过在前端路由 设置对应的配置项,根据后台返回当前的用户权限进行匹配,好处 简单易用,不好点不适合多权限配置 3.理顺一下这种方式的思路 首先需要在'路由全局守卫--beforeEach'这里配合'vuex 中action 去走用户的接口',这时候会拿到 一个用户权限的返回值类似'['super_admin'] ['super_admin', 'admin']'这种形式,将这组权限和要 访问的路径做对比看用户是否在当前权限中,来决定用户是否能跳转,因此这种方法会每次走链接 跳转的时候都会触发'路由的声明周期'来做判断 '关于菜单渲染' 在走'路由的声明周期的时候'我们会将权限存在'vuxe' 中,当菜单渲染时候,一般会在 'vuex' 中定义一个获取菜单的方法,这个方法主要会将'routers 路由文件'和'权限'进行匹配生成菜单, 也可以理解成每次输入地址后都会生成新的菜单数据 4.下面的'routes' 是将路由抽离的文件可以参看 登陆写法 ~~~ >[danger] ##### 在路由配置 ~~~ { path: '/components', name: 'components', meta: { icon: 'logo-buffer', title: '组件', access:['super_admin'] }, } ~~~ >[danger] ##### iview-admin -- 源码中路由配置 [源码地址]([https://github.com/iview/iview-admin/blob/master/src/router/index.js](https://github.com/iview/iview-admin/blob/master/src/router/index.js)) ~~~ const router = new Router({ routes, mode: 'history' }) const LOGIN_PAGE_NAME = 'login' // 用来判断当前用户是否有访问菜单的权限 // canTurnTo 返回的是布尔类型,主要用来做看当前用户权限访问的地址和菜单中 // 对应地址的权限是否相同 const turnTo = (to, access, next) => { if (canTurnTo(to.name, access, routes)) next() // 有权限,可访问 else next({ replace: true, name: 'error_401' }) // 无权限,重定向到401页面 } router.beforeEach((to, from, next) => { iView.LoadingBar.start() const token = getToken() if (!token && to.name !== LOGIN_PAGE_NAME) { // 未登录且要跳转的页面不是登录页 next({ name: LOGIN_PAGE_NAME // 跳转到登录页 }) } else if (!token && to.name === LOGIN_PAGE_NAME) { // 未登陆且要跳转的页面是登录页 next() // 跳转 } else if (token && to.name === LOGIN_PAGE_NAME) { // 已登录且要跳转的页面是登录页 next({ name: homeName // 跳转到homeName页 }) } else { if (store.state.user.hasGetInfo) { turnTo(to, store.state.user.access, next) } else { store.dispatch('getUserInfo').then(user => { // 拉取用户信息,通过用户权限和跳转的页面的name来判断是否有权限访问;access必须是一个数组,如:['super_admin'] ['super_admin', 'admin'] turnTo(to, user.access, next) }).catch(() => { setToken('') next({ name: 'login' }) }) } } }) router.afterEach(to => { setTitle(to, router.app) iView.LoadingBar.finish() window.scrollTo(0, 0) }) ~~~ >[danger] ##### 核心判断 -- canTurnTo ~~~ 1.canTurnTo 有三个参数'name 即将跳转的路由nam','access 用户权限数组','routes 路由列表' 2.返回的是布尔类型 ~~~ * 利用递归去查找所有路由,因为路由有嵌套的children 类型所以递归 ~~~ /** * 权鉴 * @param {*} name 即将跳转的路由name * @param {*} access 用户权限数组 * @param {*} routes 路由列表 * @description 用户是否可跳转到该页 */ export const canTurnTo = (name, access, routes) => { const routePermissionJudge = (list) => { return list.some(item => { if (item.children && item.children.length) { return routePermissionJudge(item.children) } else if (item.name === name) { return hasAccess(access, item) } }) } return routePermissionJudge(routes) } ~~~ * hasAccess 查router 中是否配置'access' 如果配置了,看配置的权限是否在后台返回数组中 ~~~ /** * @param {*} access 用户权限数组,如 ['super_admin', 'admin'] * @param {*} route 路由列表 */ const hasAccess = (access, route) => { if (route.meta && route.meta.access) return hasOneOf(access, route.meta.access) else return true } ~~~ * hasOneOf 查询目标数组单项是否在当前数组中 ~~~ /** * @param {Array} target 目标数组 * @param {Array} arr 需要查询的数组 * @description 判断要查询的数组是否至少有一个元素包含在目标数组中 */ export const hasOneOf = (targetarr, arr) => { return targetarr.some(_ => arr.indexOf(_) > -1) } ~~~