antd组件menu根据url实现自动高亮和展开

您所在的位置:网站首页 react导航栏组件 antd组件menu根据url实现自动高亮和展开

antd组件menu根据url实现自动高亮和展开

2023-07-21 18:44| 来源: 网络整理| 查看: 265

antd组件menu根据url自动高亮和展开

在这里插入图片描述

步骤一:封装构造函数 const MenuItem = Menu.Item; const SubMenu = Menu.SubMenu; //封装一个构造函数 class MenuNode { constructor(menuItem, parent=null) { this.key = menuItem.url || menuItem.auth_name; this.parent = parent; } } 步骤二:定义组件 constructor(props) { super(props) this.state = { //判断是否路由跳转 hash:false, //判断是否一已经获取数据 finish:false, collapsed: 0, defaultOpenKeys: [], defaultSelectedKeys: [] }; //用来存放遍历完得到的权限数组 this.menuTree = []; } // 跳转页面 jumpFn = url => { this.props.history.push(url) } 步骤三:挂载完成触发函数遍历权限,生成一个新的数组 // componentDidMount() { // 发送异步请求会会获取menu数据,这个时候再序列化menu,通过回调函数监控路由 this.props.getMenu('', () => { this.initMenu(this.props.menuList); this.setState({ finish: true }) this.setActiveMenu(this.props.history.location) }) //监控路由变化 window.addEventListener('hashchange', () => { this.setState({ hash: true }) }) } //,通过v-for循环遍历对象this.props.menu,生成一个指定格式的新的数组 initMenu = (config, parent = null) => { for (let menuItem of config) { if (menuItem.children) { //如果menuItem有children则对其children递归执行此方法,并且将当前menuItem作为父级 this.initMenu(menuItem.children, new MenuNode(menuItem, menuItem.auth_id)); } else { //如果这个路由不是没有children,则是一级路由,则直接放入menuTree中 this.menuTree.push(new MenuNode(menuItem, parent)); } } //menuTree中最终存储的是单个menuNode对象,通过判断menuNode是否有效的parent即可判断是一级路由还是子菜单下的路由 };

得到的menuTree的格式 在这里插入图片描述

步骤四:定义函数

这是自动展开和高亮的关键,同时这里可以实现防止用户输入地址进入没有权限的页面,起到拦截作用;

// 监控当前地址栏路径,遍历menu序列,找到对应的父,然后打开 setActiveMenu = location => { //拿到当前浏览器的hash路径 const pathname = location.pathname; // // 定义一个数据,判断用户是否有权限访问 for (let node of this.menuTree) { //使用正则判断当前浏览器path是否与菜单项中的key相匹配,避免路由传参 const isActivePath = new RegExp(`^${node.key}`).test(pathname); if (isActivePath) { const openKeys = []; const selectedKeys = [node.key]; //判断当前菜单是否有父级菜单,如果有父级菜单需要将其展开 while (node.parent) { openKeys.push(node.parent.key); node = node.parent; } this.setState({ defaultOpenKeys: openKeys, defaultSelectedKeys: selectedKeys }); return; } } //上面所有的地址都匹配不到就会进行拦截,显示没有权限,跳转到欢迎页 if (this.props.history.location.pathname!== '/' &&this.props.history.location.pathname!=='/welcome' &&this.props.history.location.pathname!=='/404') { this.props.history.push('/welcome') message.error('对不起,您没有权限') } // 如果一个路由都没有匹配上则关闭菜单 this.setState({ defaultSelectedKeys: [], defaultOpenKeys: [] }); }; //用于渲染路由,通过递归实现任意层级渲染 renderMenuItem = menuArr => { const ret = menuArr.map(item => { if(item.children) { return ( {this.renderMenuItem(item.children)} ); } else { return ( {item.auth_name} ); } }); return ret; } 步骤五:定义点击展开事件

vant 的defaultOpenkeys只有初次渲染的时候才生效,所以这边使用的都是openkeys,但是openkeys生效的情况下,其他导航栏无法点开,所以要绑定openchange事件,去重新修改openkeys:

// 每次点击清除openkeys,关闭其他 onOpenChange = (openKeys) => { if (openKeys.length === 0||openKeys.length===1) { this.setState({ defaultOpenKeys:openKeys }) return } const latestOpenkey = openKeys[openKeys.length - 1] if (latestOpenkey.includes(openKeys[0])) { this.setState({ defaultOpenKeys:[] }) } else { this.setState({ defaultOpenKeys:[latestOpenkey] }) } } 步骤六:渲染页面

这里如果不设置定时器,会报错: 在这里插入图片描述 这里只能在render里面触发展开事件,在componentDidMount里面触发的话只会执行一次,在render里面触发,页面切换的时候也可以再次触发,hash和finish为了限制展开事件的触发,否则render触发setActiveMenu修改state,又会重新触发render,会进入死循环:

render() { //这里不加hash去限制的话,每次触发上面的点击展开事件后会再次触发setActiveMenu事件,导致点击展开事件失效 if (this.state.finish && this.state.hash) { // 为了防止在render渲染页面的时候修改state,这里加定时器改成异步 setTimeout(() => { this.setActiveMenu(this.props.history.location) this.setState({hash:false}) }, 0) } return ( {this.renderMenuItem(this.props.menuList)} { margin: '24px 16px', padding: 24, minHeight: 280, }} > {this.props.children} ) } } // export default withRouter(Side); const mapStateToProps = state => { // console.log(state.toJS().login.menu,1111) return { menuList: state.toJS().login.menu, } } const mapDispatchToProps = dispatch => { return { getMenu: (params,callback) => dispatch(getMenuAction(params,callback)), } } export default connect(mapStateToProps,mapDispatchToProps)(withRouter(Side))

这个方法可以实现menu菜单栏刷新页面、点击菜单、输入地址都可以触发, 同时也可以从前端的角度去进行按钮权健,避免用户输入地址进入没有权限的页面



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3