• 技术文章 >web前端 >前端问答

    react怎么实现三级菜单

    藏色散人藏色散人2023-01-19 11:00:13原创50

    react实现三级菜单的方法:1、创建展开三级父级菜单的方法为“onOpenChange = (openKeys) => {...}”;2、通过“handleSelectkeys(e){...}”设置选中状态;3、通过“oli.push(<Menu.Item key={...})实现生成侧边栏即可。

    本教程操作环境: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怎么实现三级菜单的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:React
    上一篇:箭头函数属于es6吗 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • react打包图片路径错误怎么办• react怎么改字体• react element什么意思• react build 路径不对怎么办
    1/1

    PHP中文网