本文已参与「新人创作礼」活动,一起开启掘金创作之路。
umi提供了一个可以控制权限的插件plugin-access
插件用法
plugin-access约定在/access.js文件定义路由权限。
文件返回: 该文件默认导出一个函数,函数返回一个对象,函数默认传入initialState,对象里每个数据的值都为一个布尔值,表示这个变量的是否有权限。
函数返回值: 默认返回一个对象,对象的每一个键值就是一条路由,值一般为true或者false,表示是否展示这条路由。
假如有个用户页面,有个用户列表,我们要通过角色去判断用户能不能修改和删除.
// /access.js
export default function(initialState) {
const {role} = initialState;
return {
'canEdit': role === "admin",
'canDel': role === "admin",
}
}
// /user.jsx
import React from 'react';
import { useAccess } from 'umi';
import { Table } from 'antd';
const Page = props => {
const access = useAccess();
return <>
<Table columns={[
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '操作',
dataIndex: 'operates',
key: '操作',
render: (text: any, row: any) => (
<div>
{access?.canEdit && <a>编辑</a>}
{access?.canDel && <a>删除</a>}
</div>
)
},
]}/>
</>;
};
export default PageA;
使用该插件控制路由权限
- 获取有权限的路由列表 这个权限列表,我们一般从后端获取,或者通过权限去配置。 access文件传入参数initialState,所以,我们把这个列表存入initialState中,方便获取。
// app.js
export async function getInitialState() {
const menuAuthList = await request("/getMenuAuthList.json");
return {
menuAuthList
};
}
- 写本地路由 配置一个默认的本地静态路由,并在/config/config.ts中routes配置中引入 给路由配置一个access,用来定义每个路由的权限名称。
// /config/routes/index.ts
export default [
{
path: '/demo/welcome',
name: '欢迎',
icon: 'smile',
component: '@/pages/demo/welcome',
access: 'welcome'
},
{
path: '/demo/form/form-input',
name: 'antd表单项',
icon: 'smile',
component: './demo/form/form-input',
access: 'formInput'
},
]
- 通过权限列表去过滤本地路由 判断权限列表中是否存在路由中的access,如果有,就将这个权限存入对象,由于路由是一个树状结构,所以我们需要层层递归,去判断每一层的每一个路由的权限。access通过这样的配置就可以很简单的实现针对某些页面的权限控制,只要这个路由是权限文件中返回的某个为true的key值,就会展示出这个路由, 否则会默认渲染 Layout 插件内置的权限错误页面。
import { MENU_SWITCH } from '@/constants';
import route from '../config/routes';
export default function access(initialState) {
if (MENU_SWITCH) {
return true;
} else {
const { menuAuthList } = initialState || {};
let accessData = {};
const tree = (data) => {
return (data || []).map((item) => {
const { routes = [], access } = item;
if (menuAuthList.includes(newAccess)) {
accessData[access] = true;
} else {
accessData[access] = false;
}
tree(routes);
});
};
tree(route);
return accessData;
}
}