react17+antd4 Menu 点击菜单收起其他展开的所有菜单、页面刷新时设置菜单的选中状态和展开状态

这篇具有很好参考价值的文章主要介绍了react17+antd4 Menu 点击菜单收起其他展开的所有菜单、页面刷新时设置菜单的选中状态和展开状态。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

export const asyncRouterMap = [
    {
        path: '/page1',
        title: 'page1',
        icon: 'HomeOutlined',
    }, {
        path: '/page2',
        title: 'page2',
        icon: 'HomeOutlined',
    }, {
        path: '/page3',
        title: 'page3',
        icon: 'HomeOutlined',
        children: [
            {
                path: '/page301',
                title: 'page301',
                icon: 'HomeOutlined',
            }, {
                path: '/page302',
                title: 'page302',
                icon: 'HomeOutlined',
            }, {
                path: '/page303',
                title: 'page303',
                icon: 'HomeOutlined',
            }
        ]
    },{
        path: '/page4',
        title: 'page4',
        icon: 'HomeOutlined',
        children: [
            {
                path: '/page401',
                title: 'page401',
                icon: 'HomeOutlined',
            }, {
                path: '/page402',
                title: 'page402',
                icon: 'HomeOutlined',
            }
        ]
    }
]

使用path当作Menu的key.

1.菜单栏展开和回收事件

点击菜单,收起其他展开的所有菜单,只留下一个。

Menu的onOpenChange方法:SubMenu 展开/ 关闭的回调函数,展开和回收某项菜单时的事件。
Menu的openKeys属性:当前展开的SubMenu菜单项的key数组,当前菜单展开项的key数组。

当前要展开哪一项的openKeys将来是要变化的,需要存到state中。

state={
	openKey:['']
}

//展开和回收某项菜单,把openKeys的数组值变为keys数组的最后一项,只要一项是展开的,就是我刚点击的这一项
handleOpenChange=(keys)=>{
	//keys是一个字符串数组,记录了当前哪一项是展开的(用key来记录)
	
   	//console.log(keys) 
  	/* 点击page3 keys输出["",'/page3'],再点击page4 keys输出["",'/page4'],点击谁keys数组的最后一项就是谁*/
	this.setState({
      	 openKeys:[keys[keys.length-1]]
    })
}

<Menu
	defaultSelectedKeys={['/home']}
	mode="inline"
	theme="dark"
	style={{ height: "100vh" }}
	openKeys={openKeys}
	onOpenChange={this.handleOpenChange}
>

2. 刷新时默认当前选中项样式的处理

根据用户的操作习惯,选中一个二级菜单节点的时候,刷新页面的时候应该保持用户之前的选中状态,并且二级菜单展开项应该默认展开。

2.1 刷新页面菜单保持用户之前的选中状态

现在的情况是点击page2页面,组件在page2页面,在这时刷新页面,导航栏的高亮选中变成了第一项,但是组件还是page2页面,出现了选中菜单与页面不符合的情况,我们希望的是点击了刷新页面之后组件在page2页面并且导航栏选中项也是这个。

Menu的selectedKeys属性:表示当前样式所在的选中项key,不能直接写死,通过获取当前的路径拿到key。

怎么获取当前路径呢?对于类组件,使用this.props.location.pathname拿到的就是当前页面的路径;对于函数式组件,使用hooks的useLocation().pathname拿到当前页面的路径。

获取到当前页面的路径后作为值修改selectedKeys的值。

state={
	openKey:[''],
	selectedKey:['']
}


 /* this.changeSelectKeys()这个函数要在要在componentDidMount中调用一次,
 再在componentUpdate中再调用。
 这是因为componentDidMount只在第一次render之后执行一次,
 后续的rendr执行后会执行componentDidUpdate;
 从登录页进入到首页后会先mount,然后有setState,会发生update,
 点击切换菜单栏只会再执行componentUpdate,
 不会再执行componentDidMount了。*/
/*在componentDidUpdate生命周期方法中加入
判断当前页面路径是否与上一个页面路径相同
是为了避免不必要的状态更新和重新渲染,从而防止死循环的发生。
如果没有这个判断,每次组件更新时都会执行changeSelectedKey方法,
该方法会根据当前路径更新菜单状态。
然而,更新状态又会导致组件重新渲染,这将再次触发componentDidUpdate方法,形成一个无限循环。
通过添加判断,我们可以确保只有在当前页面路径与上一个页面路径不同时才会更新菜单状态,
从而避免了不必要的循环更新。*/
componentDidUpdate(prevProps) {
	// 这里必须要有这个前后路径是否一致的判断,否则会出现死循环
    if (prevProps.location.pathname !== this.props.location.pathname) {
      this.changeSelected();
    }
}
componentDidMount() {
     this.changeSelected();
}
changeSelected = () => {
    //根据当前页面路由修改当前选中的菜单项key数组
    //获取当前页面路径(切割后的key)  由于我们设计的当前页面路径与key不完全一致需要做切割
    const currentRoute = this.props.location.pathname.split('/index')[1]
    this.setState({
        selectedKey: [currentRoute]
    })
}


<Menu
	defaultSelectedKeys={['/home']}
	selectedKeys={selectedKey}
	mode="inline"
	theme="dark"
	style={{ height: "100vh" }}
	openKeys={openKeys}
	onOpenChange={this.handleOpenChange}
>

现在能够实现的是页面刷新保持用户的选中状态,但是当我们点击的是page301再刷新页面时,虽然该菜单项会被选中,但是菜单栏中page301没有被展开,需要再进行下面的配置。

2.2 配置展开项openKeys的初始值

需要修改openKeys数组,openKeys的展开项是不能写死的,刷新页面后谁展开是跟路径有关的。

整体思路是:拿着this.props.location.pathname与items数组的每一项的children的key值进行对比,如果找到了相等了,就要他上一级的key给到openKeys数组的元素,作为初始值。
(这个思路更加通用一些)

整体思路:根据this.props.location.pathname拿到它上一级的key,比如’/page3/page301’要想办法拿到‘/page3’,’/page3/page301/page30101’要想办法拿到’/page3/page301’,把openKeys的值改为拿到的它上一级的key,这个操作可以跟随changeSelectedKey操作放在一个函数中。(这种方法比较简单,但是要求key的格式必须是 /page3/page301 这样的)

    changeSelected = () => {
        //根据当前页面路由修改当前选中的菜单项key数组
        //获取当前页面路径(切割后的key)  由于我们设计的当前页面路径与key不完全一致需要做切割
        const currentRoute = this.getCurrentRoute()

        // pathname:  /home   /student/exam    /student/exam/a
        // 想要的结果  /home   /student          /student/exam
        //先拆开在拼起来
        //拆开    ['',home] ['','student','exam']    ['','student','exam','a']
        //取1~倒数第二项    ['student']   ['student','exam']
        //拼接起来
        let openKeys=[]
        if(currentRoute.split('/').length>2){
            openKeys=[`/${currentRoute.split('/').slice(1, -1).join('/')}`]
        }
        // console.log(openKeys)
        this.setState({
            selectedKey: [currentRoute],
            openKeys
        })        
    }

componentDidMount用于刷新页面时页面卸载又重新挂载,componentDidUpdate用于不刷新页面只点击菜单栏。

在使用React类组件时,调用updateMenuState方法既在componentDidMount中也在componentDidUpdate中是为了确保无论组件是在初次挂载还是在更新后,都能根据当前的路由路径正确设置菜单的选中状态和展开状态。

这两个生命周期方法各自承担着不同的职责:

  • componentDidMount:这个方法在组件首次渲染到DOM中后被调用。此时,你可以进行API调用、设置状态等操作。对于导航菜单来说,当组件首次加载时,你需要根据当前的路由路径初始化菜单的状态,包括哪个菜单项被选中以及哪些子菜单应该展开。因为在应用首次加载时,用户可能直接通过URL访问特定页面,所以需要在这个时刻根据URL设置正确的菜单状态。

  • componentDidUpdate:这个方法在组件更新后被调用。在React中,组件的更新可能由props或state的改变引起,也可能是由于父组件的重新渲染触发。在导航菜单的情况下,用户可能通过点击链接或其他方式导致路由的变化,因此需要在组件更新后再次检查当前的路由路径,以确保菜单状态与当前页面匹配。因此,在componentDidUpdate中调用updateMenuState方法,可以在组件更新后根据新的路由路径更新菜单状态,保持菜单的正确显示。

参考内容:React 中使用antd,刷新时被选中的menu二级菜单初始化的展开问题
                  React+Ant Design 4.4.1实现左侧二级导航(可配置路由、所有路由层级可统一、可根据路由高亮菜单项、刷新时可自动展开定位到当前路由)文章来源地址https://www.toymoban.com/news/detail-850316.html

到了这里,关于react17+antd4 Menu 点击菜单收起其他展开的所有菜单、页面刷新时设置菜单的选中状态和展开状态的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • uniapp实现支付宝菜单展开与收起

    需求实现支付宝类似的效果:  思路:         1.首先建立展开收起按钮,这里使用的是uview里面的icon图标。         2.其次建立展开菜单内容,这里只演示了文本信息,后期引入首页应用。         3.最后写js逻辑,展开收起时改变盒子高度和icon。 代码: 1.视图层 2.逻辑层

    2024年02月13日
    浏览(33)
  • VUE+ElementUI Table表格实现“指定行“展开并且其他行收起,“指定行”数据重复实现“合并行”

    遇到甲方爸爸一个需求,在原本的table表格中需要每一行具有下拉列表的功能,实现“指定行”展开,下拉菜单中并且含有数据属性重复的,则还需合并行。 展开行有两种方式: 方法一是利用table组件中 default-expand-all 属性,将 “内容是否存在” 作为判断条件,实现默认展开

    2024年01月23日
    浏览(40)
  • 基于Vue3实现鼠标按下某个元素进行拖动,实时改变左侧或右侧元素的宽度,以及点击收起或展开的功能

    其原理主要是利用JavaScript中的鼠标事件来控制CSS样式。大致就是监听某个DOM元素的鼠标按下事件,以及按下之后的移动事件和松开事件。在鼠标按下且移动过程中,可实时获得鼠标的X轴坐标的值,通过简单计算,可计算出目标元素的宽度,然后再用CSS赋值就实现该效果了。

    2024年02月12日
    浏览(30)
  • 基于Vue3实现鼠标按下某个元素进行移动,实时改变左侧或右侧元素的宽度,以及点击收起或展开的功能

    其原理主要是利用JavaScript中的鼠标事件来控制CSS样式。大致就是监听某个DOM元素的鼠标按下事件,以及按下之后的移动事件和松开事件。在鼠标按下且移动过程中,可实时获得鼠标的X轴坐标的值,通过简单计算,可计算出目标元素的宽度,然后再用CSS赋值就实现该效果了。

    2024年02月15日
    浏览(37)
  • react ant-design实现导航菜单menu的路由设置/切换页面

    ant-design版本是5.1.1,路由版本是v6的 新版本的导航菜单路由设置与旧版的不太一样,刚开始的时候甚至不知道该怎么写 实现效果: 代码: 首先,给导航菜单的menu添加点击事件 修改item,通过设置点击事件获取点击后的key值(key值即路由跳转的页面) 打印出来看看 获取到的

    2024年02月12日
    浏览(44)
  • React使用antd的图片预览组件,点击哪个图片就预览哪个的设置

    使用了官方推荐的相册模式的预览,但是点击预览之后,每次都是从图片列表的第一张开始预览,而不是点击哪张就从哪张开始预览: 所以这里我就封装了一下,对初始化预览的列表进行了逻辑处理: 当点击开始预览的时候,要找到当前图片在预览图列表中的索引,然后设

    2024年02月13日
    浏览(35)
  • react使用antd的table组件,实现点击弹窗显示对应列的内容

    特别提醒:不能在table的columns的render里面设置弹窗组件渲染,因为这会导致弹窗显示的始终是最后一行的内容,因为这样渲染的结果是每一行都会重新渲染一遍这个弹窗并且会给传递一个content的值,渲染到最后一行的时候,就传递的是最后一行的值。这就导致你有多少行数据

    2024年02月12日
    浏览(33)
  • element-ui中el-table点击其他自定义按钮展开table中某一行

    在日常开发中,我们遇见了会有点击某些按钮,使得表格行展开的需求,这时候去查看文档 element-ui(table) 这里官方提供了示例为在行最左侧有一个展开合并icon,但是点其他地方不能展开,我们又想点其他地方而展开 我们看见是在table-column上定了type为expand,而该列里面的

    2024年01月18日
    浏览(29)
  • vue 展开和收起

    效果图 代码块

    2024年02月11日
    浏览(27)
  • Android 键盘监听 键盘展开/收起监听

    Android 键盘的展开与收起一直是个很遭人诟病的东西 方法各式各样都有,但是基本都不是很好用,有各种限制 这里编写了一个优雅地实现方式,利用屏幕实际高度与显示区域的高度对比可以优雅地判断出是否弹出键盘. 众所周知键盘是会侵占实际应用的显示区域,导致实际显示区域

    2024年02月12日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包