react怎么实现三级菜单-LMLPHP

本教程操作环境:Windows10系统、react18.0.0版、Dell G3电脑。

react怎么实现三级菜单?

react + antd实现只展开一个父级菜单栏的侧边栏(三级菜单栏)

工作中遇到一个需求,三级侧边栏只能展开一个父级菜单栏,保持页面简洁,提高用户体验,也是在网上查了很久,也没有完全符合要求的,就结合他人的自己写了一个。。。。

展开三级父级菜单的方法

onOpenChange = (openKeys) => {
        const latestOpenKey = openKeys.find(key => this.state.openKeys.indexOf(key) === -1);
        let openList;
        if(this.state.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
            if(latestOpenKey&&latestOpenKey.length===3){
                openList = this.state.openKeys.filter((e)=>{
                    return e.length!==3;
                })
                this.setState({
                    openKeys:openList                });
            }else{
                this.setState({
                    openKeys:openKeys                });
            }           
        }else{
            if(latestOpenKey&&latestOpenKey.length===3){
                openList = this.state.openKeys.filter((e)=>{
                    return e.length!==3;
                })
                openList.push(latestOpenKey);
                this.setState({
                    openKeys:openList[1] ? openList : [openList[0],openList[2]]
                });
            }else{
                this.setState({
                    openKeys: latestOpenKey ? [latestOpenKey] : [],
                });
            }            
        }
    }
登录后复制

设置选中状态

 handleSelectkeys(e){
        if(this.state.isShow){
            this.setState({ 
                selectedKey:e.key,
                openKeys:e.keyPath[length] == 3  ? [e.keyPath[2],e.keyPath[1]] : [e.keyPath[0]],
                isShow:true
             }); 
        }       
    }
登录后复制

生成侧边栏

const data = this.props.list;
        var html = [];
        for(var i=0;i<data.length;i++){
            if(data[i].children){
                var li = []
                for(var j=0;j<data[i].children.length;j++){
                    var liData = data[i].children[j];
                    if(liData.children){
                        var oli = [];
                        for(var k=0;k<liData.children.length;k++){
                            oli.push(
                                <Menu.Item key={liData.children[k].url}>
                                    <Link to={
                                        {
                                            pathname:liData.children[k].url,
                                            state:{//三级菜单下传openKeys传两个值,展开两级
                                                parent:this.state.openKeys[0],
                                                child:this.state.openKeys[1]
                                            }
                                        }
                                    }>
                                        <span>{liData.children[k].text}</span>
                                    </Link>
                                </Menu.Item>
                            )
                        }
                        var oul = <SubMenu key={liData.id} title={<span>{liData.iconCls && <Icon type={liData.iconCls} />}<span>{liData.text}</span></span>}>{oli}</SubMenu>;
                        li.push(oul);
                    }else{
                        li.push(
                            <Menu.Item key={liData.url}>
                                <Link to={
                                    {
                                        pathname:liData.url,
                                        state:{//二级菜单下openKeys传一个值,展开一级
                                            parent:this.state.openKeys[0],
                                            // child:this.state.openKeys[1] ? this.state.openKeys[1] : ''
                                        }
                                    }
                                    
                                    } >
                                    {liData.iconCls && <Icon type={liData.iconCls} />}
                                    <span>{liData.text}</span>
                                </Link>
                            </Menu.Item>
                        );
                    }
                }
                var ul = <SubMenu key={data[i].id} title={<span>{data[i].iconCls && <Icon type={data[i].iconCls} />}<span>{data[i].text}</span></span>}>{li}</SubMenu>;
                html.push(ul);
            }else{
                html.push(
                    <Menu.Item key={data[i].url}>
                        <Link to={                           
                            {
                                pathname:data[i].url,
                                state:{//一级菜单下传空值,不展开菜单栏
                                    parent:''
                                }
                            }
                            } >
                            {data[i].iconCls && <Icon type={data[i].iconCls} />}
                            <span>{data[i].text}</span>
                        </Link>
                    </Menu.Item>
                )
            }
        }
登录后复制

侧边栏组件Menu.js 全部代码

import React from 'react'import { Menu,Icon } from 'antd';import {Link,withRouter} from 'react-router-dom'const { SubMenu } = Menu;

 class Menus extends React.Component{
    constructor(props){
        super(props)
        this.state={
            openKeys:['1','100'],
            rootSubmenuKeys:[],
            selectedKeys:[this.props.history.location.pathname], //选中
            isShow:false //判断是否已经展开,如已展开停止重新赋值避免重新渲染和关系菜单         
        }
        this.handleSelectkeys = this.handleSelectkeys.bind(this)
    }
    UNSAFE_componentWillMount(){
        if(this.props.location.state){
            this.setState({
                openKeys:[this.props.location.state.parent,this.props.location.state.child ? this.props.location.state.child : '']
            })           
        }
          
      }
    componentDidMount(props,nextProps){
        var data = this.props.list;
        for(var i=0;i<data.length;i++){
            if(data[i].children){
                for(var j=0;j<data[i].children.length;j++){
                    var liData = data[i].children[j];
                    if(liData.children){
                        this.state.rootSubmenuKeys.push(liData.id+"");
                    }
                }
                this.state.rootSubmenuKeys.push(data[i].id+"");
            }
        }
        // 刷新菜单更新默认状态
        const { pathname } = this.props.history.location;
        const rank = pathname.split('/')
        switch (rank.length) {
          case 2 :  //一级目录
            this.setState({
              selectedKeys: [pathname]
            })
            break;
          case 5 : //三级目录,要展开两个subMenu
            this.setState({
              selectedKeys: [pathname],             
            })
            break;
          default :
            this.setState({
              selectedKeys: [pathname],
            })
        }
       
        // 浏览器前进后退按钮更新菜单状态
        if (window.history && window.history.pushState) {
            window.onpopstate = function () {
                window.location.reload(true); //刷新页面
            };
        }
    }
    handleSelectkeys(e){
        if(this.state.isShow){
            this.setState({ 
                selectedKey:e.key,
                openKeys:e.keyPath[length] == 3  ? [e.keyPath[2],e.keyPath[1]] : [e.keyPath[0]],
                isShow:true
             }); 
        }       
    }
    onOpenChange = (openKeys) => {
        const latestOpenKey = openKeys.find(key => this.state.openKeys.indexOf(key) === -1);
        let openList;
        if(this.state.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
            if(latestOpenKey&&latestOpenKey.length===3){
                openList = this.state.openKeys.filter((e)=>{
                    return e.length!==3;
                })
                this.setState({
                    openKeys:openList                });
            }else{
                this.setState({
                    openKeys:openKeys                });
            }           
        }else{
            if(latestOpenKey&&latestOpenKey.length===3){
                openList = this.state.openKeys.filter((e)=>{
                    return e.length!==3;
                })
                openList.push(latestOpenKey);
                this.setState({
                    openKeys:openList[1] ? openList : [openList[0],openList[2]]
                });
            }else{
                this.setState({
                    openKeys: latestOpenKey ? [latestOpenKey] : [],
                });
            }            
        }
    }
    render(){
        const data = this.props.list;
        var html = [];
        for(var i=0;i<data.length;i++){
            if(data[i].children){
                var li = []
                for(var j=0;j<data[i].children.length;j++){
                    var liData = data[i].children[j];
                    if(liData.children){
                        var oli = [];
                        for(var k=0;k<liData.children.length;k++){
                            oli.push(
                                <Menu.Item key={liData.children[k].url}>
                                    <Link to={
                                        {
                                            pathname:liData.children[k].url,
                                            state:{//三级菜单下传openKeys传两个值,展开两级
                                                parent:this.state.openKeys[0],
                                                child:this.state.openKeys[1]
                                            }
                                        }
                                    }>
                                        <span>{liData.children[k].text}</span>
                                    </Link>
                                </Menu.Item>
                            )
                        }
                        var oul = <SubMenu key={liData.id} title={<span>{liData.iconCls && <Icon type={liData.iconCls} />}<span>{liData.text}</span></span>}>{oli}</SubMenu>;
                        li.push(oul);
                    }else{
                        li.push(
                            <Menu.Item key={liData.url}>
                                <Link to={
                                    {
                                        pathname:liData.url,
                                        state:{//二级菜单下openKeys传一个值,展开一级
                                            parent:this.state.openKeys[0],
                                            // child:this.state.openKeys[1] ? this.state.openKeys[1] : ''
                                        }
                                    }
                                    
                                    } >
                                    {liData.iconCls && <Icon type={liData.iconCls} />}
                                    <span>{liData.text}</span>
                                </Link>
                            </Menu.Item>
                        );
                    }
                }
                var ul = <SubMenu key={data[i].id} title={<span>{data[i].iconCls && <Icon type={data[i].iconCls} />}<span>{data[i].text}</span></span>}>{li}</SubMenu>;
                html.push(ul);
            }else{
                html.push(
                    <Menu.Item key={data[i].url}>
                        <Link to={                           
                            {
                                pathname:data[i].url,
                                state:{//一级菜单下传空值,不展开菜单栏
                                    parent:''
                                }
                            }
                            } >
                            {data[i].iconCls && <Icon type={data[i].iconCls} />}
                            <span>{data[i].text}</span>
                        </Link>
                    </Menu.Item>
                )
            }
        }
        return (
            <Menu 
                openKeys={this.state.openKeys}
                selectedKeys={[this.props.history.location.pathname]}
                onClick={this.handleSelectkeys}
                onOpenChange={this.onOpenChange}
                mode="inline"
                theme="dark"
                collapsed={this.state.collapsed}>
                {html}
            </Menu>
        )
    }}export default withRouter(Menus);
登录后复制

侧边栏数据 menu.js

const list = [
  {
      "id":1,
      "text":"检查清单",
      "state":"closed",
      "iconCls":"home",
      "children":[
          {
              "id":100,
              "text":"按月检查",
              "checked":false,
              "state":"closed",
              "iconCls":"",
              "url":"/platform/check/month"
          },
          {
              "id":101,
              "text":"按年检查",
              "checked":false,
              "state":"closed",
              "iconCls":"",
              "url":"/platform/check/year"
          }
      ]   
  },
  {
      "id":2,
      "text":"数据预览导出",
      "iconCls":"laptop",
      "state":"closed",
      "checked":true,
      "children":[
          {
              "id":200,
              "text":"做的书",
              "iconCls":"",
              "state":"closed",
              "checked":true,
              "children":[
                  {
                      "id":20001,
                      "text":"2018做的书",
                      "iconCls":" ",
                      "url":"/platform/export/makeBook/2018"
                  },
                  {
                      "id":20002,
                      "text":"2019做的书",
                      "iconCls":" ",
                      "url":"/platform/export/makeBook/2019"
                  },
                  {
                      "id":20003,
                      "text":"2020做的书",
                      "iconCls":" ",
                      "url":"/platform/export/makeBook/2020"
                  }
              ]
          },
          {
              "id":201,
              "text":"财务收入",
              "iconCls":"",
              "state":"closed",
              "checked":true,
              "children":[
                  {
                      "id":20101,
                      "text":"2018财务收入",
                      "iconCls":" ",
                      "url":"/platform/export/GMV/2018"
                  },
                  {
                      "id":20102,
                      "text":"2019财务收入",
                      "iconCls":" ",
                      "url":"/platform/export/GMV/2019"
                  },
                  {
                      "id":20103,
                      "text":"2020财务收入",
                      "iconCls":" ",
                      "url":"/platform/export/GMV/2020"
                  },
              ]
          },
          {
              "id":202,
              "text":"财务支出",
              "iconCls":"",
              "state":"closed",
              "checked":true,
              "children":[
                  {
                      "id":20201,
                      "text":"2018财务支出",
                      "iconCls":" ",
                      "url":"/platform/export/expend/2018"
                  },
                  {
                      "id":20202,
                      "text":"2019财务支出",
                      "iconCls":" ",
                      "url":"/platform/export/expend/2019"
                  },
                  {
                      "id":20203,
                      "text":"2020财务支出",
                      "iconCls":" ",
                      "url":"/platform/export/expend/2020"
                  },
              ]
          },
         ]
  },
 ]class SiderNav extends React.Component {
  render() {
    return (   
      <Sider  width={230}  breakpoint  className="AdminSider">
          <Menus list={list} />
      </Sider>
    )
  }}```
登录后复制

推荐学习:《react视频教程

以上就是react怎么实现三级菜单的详细内容,更多请关注Work网其它相关文章!

08-31 20:59