CLI — 简单权限
最后更新于:2022-04-02 08:10:13
>[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)
}
~~~
';