菜单还承担着页面导航的功能
多级菜单
菜单项的子页面,如何高亮其隶属于的父级菜单
如点击门店管理中的某一个门店进入的门店详情页在菜单中并没有对应的菜单项
selectedKeys,Array 当前选定的菜单项
openKeys,Array 多个多级菜单的打开状态
selectedKeys,openKeys的区别:
- 在 selectedKeys 不变的情况下,在打开或关闭其他多级菜单后,openKeys 是会发生变化的
- 对于 selectedKeys 是由页面路径 location.pathname决定的,每一次 pathname 发生变化都需要重新计算 selectedKeys 的值
selectedKeys
selectedKeys,Array 当前选定的菜单项
selectedKeys 由传入的 pathname 决定
所以,将 selectedKeys 与 pathname 之间的转换关系封装在组件中
只需要传入正确的 pathname 就可以获得相应的 selectedKeys
memoize-one
通过 location.pathname 以及菜单数据 menuData 去计算 selectedKeys,是个耗费性能的计算。
memoize-one 在每次调用函数之前
- 先检查传入的参数是否与上一个执行过的参数完全相同,
- 如果完全相同,就直接返回上次计算过的结果,就像缓存一样 ```jsx import memoize from ‘memoize-one’;
const memoMenuData = memoize(menuData => menuData);
const selectedKeys = memoize((pathname, menuData) => getMeunMatchKeys(getFlatMenuKeys(menuData), urlToList(pathname)) );
使用侧边栏组件时,只需要将应用当前的页面路径 location.pathname,传递给组件中的 pathname 属性即可,<br />侧边栏组件会自动处理:
- 菜单高亮 selectedKeys
- 多级菜单的打开与关闭 openKeys
<a name="TzzG6"></a>
### MenuItem
- 根据 props 传来的 pathname 及 menuData 计算出当前的 selectedKeys,
- 将 selectedKeys 当做 openKeys 的初始值,初始化组件内部 state
- 因为 openKeys 是由用户所控制的,后续 openKeys 值的更新,有 Menu 组件的 onOpenChange函数更新
- 这样就实现了对 selectedKeys 及 openKeys 的管理
```jsx
function App() {
const [openKeys, setOpenKeys] = useState([]);
const [selectedKeys, setSelectedKeys] = useState([]);
function onOpenChange(openKeys) {
setState(openKeys);
}
const selectedKeys = memoize((pathname, menuData) =>
getMenuMatchKeys(getFlatMenuKeys(menuData), urlToList(pathname))
);
return (
<Menu
mode="inline"
theme="dark"
openKeys={openKeys}
selectedKeys={selectedKeys}
onOpenChange={onOpenChange}
>
{renderMenu(menuData)}
</Menu>
);
}
props与state的划分
一个数据如果想成为 props 就必须是组件内部无法获得的
state,对内部数据状态的严格控制
如果一个数据想成为 state,那么它就不应该,再能够被组件外部的值所改变
openKeys
openKeys,Array 多个多级菜单的打开状态
openKeys 作为组件内部的 state,初始值可以由 pathname 计算而来,
后续的更新则与组件外部的数据无关而是会根据用户的操作在组件内部完成
那么 openKeys就是一个 state,与其相关的所有逻辑都可以彻底地被封装在组件内部而不需要暴露给使用者