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

菜单栏展开回收、页面刷新时确保菜单状态与当前页面匹配

  • 1.菜单栏展开和回收事件
  • 2. 刷新时默认当前选中项样式的处理
    • 2.1 刷新页面菜单保持用户之前的选中状态
    • 2.2 配置展开项openKeys的初始值

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]]})
}<MenudefaultSelectedKeys={['/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]})
}<MenudefaultSelectedKeys={['/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实现左侧二级导航(可配置路由、所有路由层级可统一、可根据路由高亮菜单项、刷新时可自动展开定位到当前路由)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/811886.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux上下载部署zentao v15.5及具体的使用

1.先查询一下Linux的操作系统的位数&#xff0c;确保下载的文件位数与os的一致 [rootlocalhost xiaoming]# uname -m x86_64 [rootlocalhost xiaoming]# getconf LONG_BIT 64 2.下载zentao的Linux压缩包 wget https://www.zentao.net/dl/zentao/15.5/ZenTaoPMS.15.5.zbox…

vue创建一个项目

要创建一个Vue项目&#xff0c;你可以使用Vue CLI&#xff08;命令行界面&#xff09;这个官方工具。以下是使用Vue CLI创建一个新项目的步骤&#xff1a; 步骤 1: 安装 Node.js 和 npm 首先&#xff0c;确保你的计算机上已经安装了Node.js和npm&#xff08;Node.js的包管理器…

【opencv】示例-inpaint.cpp 图像修复是通过填充损坏图像部分从而修复这些损坏的过程...

原始图像 这段代码展示了一个使用OpenCV库进行图像修复的例子。它首先包含了处理图像编码、解码、显示、处理和照片处理所必要的OpenCV模块的头文件。然后利用cv和std命名空间下的类和方法。通过定义一个鼠标回调函数onMouse来处理图像上的绘图操作&#xff0c;并通过主函数mai…

基于大数据的全国热门景点数据可视化分析系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 本文将介绍如何使用Python中的Pandas库进行数据挖掘&#xff0c;并结合Flask Web框架实现一个旅游景点数据分析系统。该系统将包括以下功能模块&#xff1a;热门景点概况、景点星级与评分分析、景…

贪心:P2240 【深基12.例1】部分背包问题

目录 【深基12.例1】部分背包问题题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 代码实现 【深基12.例1】部分背包问题 题目描述 阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 N ( N ≤ 100 ) N(N \le 100) N(N≤100) 堆金币&#xff0c;第 i i i 堆金币的总重…

如何使用 Grafana 监控文件系统状态

当 JuiceFS 文件系统部署完成并投入生产环境&#xff0c;接下来就需要着手解决一个非常重要的问题 —— 如何实时监控它的运行状态&#xff1f;毕竟&#xff0c;它可能正在为关键的业务应用或容器工作负载提供持久化存储支持&#xff0c;任何小小的故障或性能下降都可能造成不利…

已解决java.net.NoRouteToHostException: 无法到达主机异常的正确解决方法,亲测有效!!!

已解决java.net.NoRouteToHostException: 无法到达主机异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 报错原因 解决思路 解决方法 检查网络连接 核实目标地址 检查防火墙和路由器规则 验证VPN/代理设置 修正网络配置 …

Django 实现登录功能

基本实现 路由 from django.urls import path from . import viewsapp_name index urlpatterns [path(, views.index, nameindex),path("login.html/", views.login, name"login"), ]视图 from django.shortcuts import render, redirect from django…

MR混合现实情景实训教学系统在旅游管理课堂上的应用

旅游管理是一门实践性很强的学科&#xff0c;需要学生掌握理论知识的同时&#xff0c;能够在实际工作中灵活运用。传统的课堂教学方式往往只能通过理论讲解和简单的模拟操作来培养学生的实践能力&#xff0c;而MR混合现实情景实训教学系统则可以为学生提供更加真实、生动的实践…

go第三方库go.uber.org介绍

Uber 是一家美国硅谷的科技公司&#xff0c;也是 Go 语言的早期 adopter。其开源了很多 golang 项目&#xff0c;诸如被 Gopher 圈熟知的 zap、jaeger 等。2018 年年末 Uber 将内部的 Go 风格规范 开源到 GitHub&#xff0c;经过一年的积累和更新&#xff0c;该规范已经初具规模…

HCIP-Datacom(H12-821)题库补充(4月12日)

最新 HCIP-Datacom&#xff08;H12-821&#xff09;完整题库请扫描上方二维码访问&#xff0c;持续更新中。 在BGP进程下&#xff0c;Aggregate命令中的detail&#xff3f;suppressed关键字的作用是以下哪一项&#xff1f; A&#xff1a;抑制生成的聚合路由下发IP路由表 B&…

vueRouter动态路由(实现菜单权限控制)

一、权限控制管理&#xff1a; 对于企业级的项目, 我们可能需要对项目做权限控制管理, 实现不同角色的用户登录项目根据所拥有的权限访问不同的页面内容&#xff0c;此时就需要使用到动态路由来对权限页面做限制。 【使用vue-router实现动态路由&#xff0c;达到实现菜单权限…

数据仓库的—数据仓库的体系架构

数据仓库通常采用分层的体系架构设计,作为支撑企业决策分析需求的数据基础设施。典型的数据仓库体系架构由以下三个核心层次组成: 源数据层(Source Layer) 这是数据仓库的数据来源,包括组织内部的各种运营系统,如ERP、CRM、SCM等,以及外部数据源如互联网、社交媒体等。这些系…

2023年全国职业技能大赛“信息安全与评估”国赛模拟题-windows应急响应+题目+WP

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏 == 养成习惯(一键三连)😋 🎉欢迎关注💗一起学习👍一起讨论⭐️一起进步�…

React + three.js 实现人脸动捕与3D模型表情同步

系列文章目录 React 使用 three.js 加载 gltf 3D模型 | three.js 入门React three.js 3D模型骨骼绑定React three.js 3D模型面部表情控制React three.js 实现人脸动捕与3D模型表情同步 示例项目(github)&#xff1a;https://github.com/couchette/simple-react-three-facia…

BI数据分析软件:行业趋势与功能特点剖析

随着数据量的爆炸性增长&#xff0c;企业对于数据的需求也日益迫切。BI数据分析软件作为帮助企业实现数据驱动决策的关键工具&#xff0c;在当前的商业环境中扮演着不可或缺的角色。本文将从行业趋势、功能特点以及适用场景等方面&#xff0c;深入剖析BI数据分析软件&#xff0…

LeetCode:1两数之和 C语言

1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以…

IP证书申请流程

目录 域名与IP的关系 SSL证书绑定域名还是绑定IP&#xff1f; IP证书支持免费申请吗&#xff1f; 如何申请IP地址证书 IP类型的SSL证书&#xff0c;又称之为IP SSL&#xff0c;这种SSL证书是专门用于公网IP地址验证的一种数字证书。 主要功能就是解决IP地址明文传输的安全…

毅四捕Go设计模式笔记——代理模式

代理模式&#xff08;Proxy Pattern&#xff09; 为了解决什么问题&#xff1f; 代理模式用于在不直接访问实际对象的情况下&#xff0c;通过引入一个代理对象来控制和管理对该对象的访问。主要解决的问题是对原始对象的访问控制&#xff0c;以及在不改变原始对象接口的情况下…

IvorySQL 3.2原理解析|与Oracle 12c XML函数兼容性的实现机制

[发行日期&#xff1a;2024年4月11日] IvorySQL 3.2基于PostgreSQL 16.2&#xff0c;引入了多种Oracle XML函数的全面兼容性功能&#xff0c;同时修复了多个问题&#xff0c;更多信息请参考文档网站。 >>>新版本体验链接&#xff1a; https://docs.ivorysql.org/cn…