如何优雅地在vue中添加权限控制示例详解

2020-06-14 05:58:07易采站长站整理

* @param {Array<any>} children - 子列表
*/
function createRedirectFn (redirect = {}, children = []) {
// 避免缓存太大,只保留 children 的 name 和 permissions
const permissionChildren = children.map(({ name = '', meta: { permissions = [] } = {} }) => ({ name, permissions }))
return function (to) {
// 这里一定不能在 return 的函数外面筛选,因为权限是异步获取的
const hasPermissionChildren = permissionChildren.filter(item => includePermission(item.permissions))
// 默认填写的重定向的 name
const defaultName = redirect.name || ''
// 如果默认重定向没有权限,则从 children 中选择第一个有权限的路由做重定向
const firstPermissionName = (hasPermissionChildren[0] || { name: '' }).name
// 判断是否需要修改默认的重定向
const saveDefaultName = !!hasPermissionChildren.find(item => item.name === defaultName && defaultName)
if (saveDefaultName) return { name: defaultName }
else return firstPermissionName ? { name: firstPermissionName } : redirect
}
}

然后我们就可以改写为:


// 我们需要引入判断权限方法
import { includePermission, createRedirectFn } from '@/utils/permission'

const children = [
{
path: 'list',
name: 'UserList',
label: '用户列表',
meta: {
permissions: ['U_1_1'] }
},
{
path: 'group',
name: 'UserGroup',
label: '用户组',
meta: {
permissions: ['U_1_2'] }
}
]

const routeDemo = {
path: '/user',
name: 'User',
label: '用户',
redirect: createRedirectFn({ name: 'UserList' }, children),
children
}

这样稍微简洁一些,但我还是需要一个一个路由去修改,所以我又写了一个方法来递归 router 配置,并重写他们的 redirect:


// @/utils/permission
/**
* 创建有权限的路由配置(多级)
* @param {Object} config - 路由配置对象
* @param {Object} config.redirect - 必须是 children 中的一个,并且使用 name
*/
function createPermissionRouter ({ redirect, children = [], ...others }) {
const needRecursion = !!children.length
if (needRecursion) {
return {
...others,
redirect: createRedirectFn(redirect, children),
children: children.map(item => createPermissionRouter(item))
}
} else {
return {
...others,
redirect
}
}
}

这样我们只需要在最外层的 router 配置加上这样一层函数就可以了:


import { createPermissionRouter } from '@/utils/permission'

const routesConfig = [
{
path: '/user',
name: 'User',
label: '用户',
meta: {
permissions: ['U_1'] },