在react项目中使用antd进行集成的时候,用到了menu做导航栏菜单项。
根据用户的操作习惯,选中一个菜单节点的时候,刷新页面的时候应该保持用户之前的选中状态。
今天恰巧碰到了这个问题,于是尝试了解决方案。
查看了一下antd中menu的API,定义如下
openKeys | 当前展开的 SubMenu 菜单项 key 数组 | string[] | |
selectedKeys | 当前选中的菜单项 key 数组 | string[] |
用到的就是这两个属性值,我们可以在menu中引用他,然后在state中进行配置
constructor(props) {
super(props);
this.state = {
openKeys: [],
selectedKeys: []
};
}
然后在render函数中的menu中绑定
render() {
return (
<div style={{ width: '100%' }}>
<Menu
theme="dark" mode="inline" onClick={this.menuClick} selectedKeys={this.state.selectedKeys} openKeys={this.state.openKeys}
>
{
this.props.menus.map((item) => {
return item.subs ? this.getParentMenu(item) : this.getChildrenMenu(item)
})
}
</Menu>
</div>
);
}
我们知道页面刷新之后会在render执行之后去调用componentDidMount函数,那我们可以在我们的menu菜单都被渲染之后在componentDidMount中写我们的菜单选中逻辑。
componentDidMount() {
// 获取当前路径
const pathname = this.props.location.pathname
//获取当前所在的目录层级
const rank = pathname.split('/')
//rank = ["","policy-engine","nas-client"]
switch (rank.length) {
case 2: //一级目录
this.setState({
selectedKeys: [pathname]
})
break;
case 3: //二级目录,要展开一个subMenu
this.setState({
selectedKeys: [pathname],
openKeys: [rank.slice(0, 2).join('/')]
})
break;
case 4: //三级目录,要展开两个subMenu
this.setState({
selectedKeys: [pathname],
openKeys: [rank.slice(0, 2).join('/'), rank.slice(0, 3).join('/')]
})
break;
}
}
其中selectedKeys存储当前选中的路径,是个数组
而openKeys存储的是当前要打开的路径,如果当前选中三级菜单节点,那么这个打开的路径就应该是['一级菜单节点路径','二级菜单节点路径']。依次类推。
这里需要注意的是使用split("/")函数时,我的路径是以"/"开头的,所以即便是二级菜单,那么它对应的长度应该是3,而不是二,当然你也可以将null或者"'删除之后,保留和菜单对应的层级数。这里就不再处理了。