react 实现权限管理和页面动态渲染树形控件

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>
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值