react权限管理
后端数据返回示例
{
code: 200,
userInfo: {
name: '李四',
age: '22',
sex: '男'
},
menuInfo: [
{
menuId: 0,
menuName: "首页",
menuUrl: "/home/table",
pathname: "Dish",
componentPath: "Table",
menuImgClass: 'el-icon-dish',
menuState: "0",
menuChilds: []
}, {
menuId: 1,
menuName: "菜品管理",
menuUrl: "/home/Dish",
pathname: "Dish",
componentPath: "Dish",
menuImgClass: 'el-icon-dish',
menuState: "0",
menuChilds: [{
menuId: 9,
menuName: "菜品设置",
menuUrl: "/home/Dish/DishSetList",
pathname: "DishSetList",
componentPath: "DishSetList",
menuImgClass: '',
menuState: "0",
menuChilds: []
},
]
}
登陆之后 将数据保存在mobx或者redux中,再通过session进行本地存储,将数据注入到index中,在需要的页面进行调用
使用之前,大家先去了解一下mobx和redux如何使用
我这里有两篇文章简单介绍:
react+redux
react+mobx
我这里用的是mobx
状态管理器中:
import {observable, action} from 'mobx'
class userStore {
@observable user = JSON.parse(sessionStorage.getItem('user'))||{}
@observable menu = JSON.parse(sessionStorage.getItem('menu'))||{}
@observable isLogin = false
@observable token = ""
@action
login(user, token) {
this.user = user;
this.token = token;
this.isLogin = true
sessionStorage.setItem('user',JSON.stringify(user))
}
setMenu(menu) {
sessionStorage.setItem('menu',JSON.stringify(menu))
this.menu = menu;
}
}
export default userStore
index.js入口文件中
index注入:
<Provider {...store}>
<App/>
</Provider>,
在菜单组件中进行调用,这里使用了迭代思想,通过判断其是否有子路由进行迭代处理,动态的生成菜单
import React from 'react'
import {Menu} from "antd";
import {Link} from "react-router-dom";
import {inject, observer} from "mobx-react";
const {SubMenu} = Menu;
//此处要引用mobx中的user
@inject('user')
@observer
class Nav extends React.Component {
constructor(props) {
super(props);
this.state = {
menuList: this.props.user.menu
}
}
bindMenu(menulist) {
let MenuList = menulist.map((item) => {
if (item.menuState !== "1") {
if (item.menuChilds.length === 0) {
return <Menu.Item key={item.menuId}>
<Link to={item.menuUrl}>{item.menuName}</Link>
</Menu.Item>
} else {
return <SubMenu key={item.menuId} title={item.menuName}>
{this.bindMenu(item.menuChilds)}
</SubMenu>
}
}
});
return MenuList
}
render() {
let list = this.bindMenu(this.state.menuList);
return (
<Menu
mode="inline"
style={{height: '100%', borderRight: 0}}
theme="dark"
multiple={false}
className="menuList"
>
{list}
</Menu>
)
}
}
export {Nav as default}
在路由组件中生成动态的路由,也是通过迭代的思想进行判断子路由,进行添加。这里会遇到一个问题。同级路由和子路由之间的生成,什么时候使用嵌套路由,什么时候直接使用同级路由。
import React from 'react'
import {Route, Switch} from 'react-router-dom'
import {inject, observer} from "mobx-react";
import loadable from '@loadable/component'
@inject('user')
@observer
class Routes extends React.Component {
constructor(props) {
super(props);
this.state = {
routeList: this.props.user.menu
}
}
setRoute(menuList) {
let RouteList = menuList.map((item) => {
if (item.menuChilds.length === 0) {
return <Route key={item.menuId} path={item.menuUrl}
component={loadable(() => import(`../pages/${item.componentPath}`))}/>
} else {
return [...this.setRoute(item.menuChilds), <Route key='00' path="/home" exact component={loadable(() => import('../pages/Index'))}></Route>]
})
return RouteList
}
render() {
let Routes = this.setRoute(this.state.routeList)
return (
<Switch>
{this.props.location.pathname !== "/login" && this.props.user.isLogin === false ?
window.location.href='/login' : Routes}
</Switch>
)
}
}
export {Routes as default}
注:本文使用antd UI框架
动态绑定到页面的树形控件上去。
constructor() {
super();
this.state = {
modalRightInfoVisible: false,//模态框弹出
RoleHasRouter: []//需要动态绑定到树形控件上的路由id
}
}
//处理拿到的当前角色的menuInfo
getRouterId(menuInfo) {
let RouterId=[];
for (let i = 0; i < menuInfo.length; i++) {
if (menuInfo[i].menuState !== "1") {
if (menuInfo[i].menuChilds.length === 0) {
RouterId.push(menuInfo[i].menuId + '')
} else {
RouterId.push(menuInfo[i].menuId + '')
this.getRouterId(menuInfo[i].menuChilds)
}
}
}
for (let i = 0; i < RouterId.length; i++) {
if (RouterId[i].length > 2) {
RouterId.splice(i, 1)
}
}
return RouterId
}
//点击授权打开弹出框,实现动态绑定数据的函数
openModalRightInfo(id) {
//这里是返回角色信息时已经返回对应权限,所以需要从数组中获取值
let data = [];
for (let i = 0; i < this.state.RoleList.length; i++) {
if (id === this.state.RoleList[i].role_id) {
data = this.state.RoleList[i].menuInfo
}
}
this.setState({
RoleHasRouter: this.getRouterId(data)
})
this.setState({modalRightInfoVisible: true});
}
//生成树形控件
SetRouter(RouterList) {
let checkBox = RouterList.map((item) => {
if (item.menuState !== "1") {
if (item.menuChilds.length === 0) {
return <TreeNode title={item.menuName} key={item.menuId} checkable/>
} else {
return <TreeNode
title={item.menuName}
key={item.menuId}
>
{this.SetRouter(item.menuChilds)}
</TreeNode>
}
}
})
checkBox = checkBox.filter(function (val) {
return !(!val || val === "");
})
return checkBox
}
//树形控件选中状态发生改变
onRouterSelectData = (checkedKeys) => {
this.setState({
RoleHasRouter:checkedKeys
})
// this.state.RoleHasRouter = checkedKeys
}
//授权弹出框
<Modal title="授权"
visible={this.state.modalRightInfoVisible}
cancelText='取消'
okText='修改'
onCancel={() => {
this.setState({
modalRightInfoVisible: false,
RoleHasRouter:[]
})
}}
onOk={() => {
this.setRouterRight()
}}
>
<div className='checkBox'>
<Tree
checkable
onCheck={this.onRouterSelectData.bind(this)}
checkedKeys={this.state.RoleHasRouter}
>
{this.SetRouter(this.state.RouterList)}
</Tree>
</div>
</Modal>