最近用到antd
的menu
导航菜单组件,官网中默认选中菜单功能defaultSelectedKeys
只能默认选中已有的菜单,对于不在菜单中的内嵌子页面并不能默认选中父菜单,菜单没有选中状态。所以我要想办法得到内嵌子页面的父菜单,放到defaultSelectedKeys
中。
比如当前的菜单的url是: http://xxx.com/system/user/detail/789404
我要在菜单数组中匹配到最相近的父菜单:
menus = [
{url: '/', name: '首页'},
{url: '/system', name: '系统'},
{url: '/system/user', name: '用户', children: [{url: '/system/user/detail', name: '用户详情'}]},
{url: '/system/role', name: '角色', children: [{url: '/system/role/detail', name: '角色详情'}]},
{url: '404', name: '404'},//会有一些乱七八糟的路径
...
]
也就是: /system/user/detail/
用了react-router-dom
的matchPath
方法,只能精确的匹配路径,看来要自己写了。。。
根据群友的提示,想到了用js的match
大法
image.png
由此可看出match
能筛选出包含有字符串的路径,好的成功了第一步!
但是也发现了match
会把404这种路径都筛选出来了,换成startsWith
会更好!
image.png
第二步就是将这些筛选出来的路径进行进一步取值,根据规律可看出路径url.length
最长的就是最匹配的
resultMenu= menus.reduce((acc, cur) => (acc.url.length > cur.url.length) ? acc : cur)
完整代码:
/**
pathname: '/system/user/detail/789404'
menus: 菜单数组
*/
getMenuPath = (pathname, menus) => {
let result = [] //模糊匹配到的路径
let resultMenu = [] //最终匹配到的路径
// 得到所有的模糊匹配路径
const foo = (_menus) => {
_menus.forEach(_menu => {
const { url, children, ...rest } = _menu
// 用startsWith匹配到开头路径
if (url && pathname.startsWith(url) && !Array.isArray(children)) {
result = result.concat([{ url, ...rest }])
} else if (Array.isArray(children)) {
//如果还有children 深层递归
foo(children)
}
})
}
foo(copyJson(menus))
if (result.length > 0) {
// 得到最近似精确的匹配路径 url越长说明越精确
resultMenu= result.reduce((acc, cur) => (acc.url.length > cur.url.length) ? acc : cur)
}
return resultMenu
}
const menus = [
{url: '/', name: '首页'},
{url: '/system', name: '系统'},
{url: '/system/user', name: '用户', children: [{url: '/system/user/detail', name: '用户详情'}]},
{url: '/system/role', name: '角色', children: [{url: '/system/role/detail', name: '角色详情'}]},
{url: '404', name: '404'}//会有一些乱七八糟的路径
]
const pathname = location.pathname
//调用
getMenuPath(pathname, menus)
最终获取到的路径是:{url: '/system/user/detail', name: '用户详情'}
,完美解决问题。如有更好的解决方法,跪求留言指教
END-----------------------------------------------
tips: 简书上交流可能会看不到消息,如有问题,欢迎进群交流50063010