如何修改递归代码从globalRoutes筛选符合menuRoutes的菜单数据?
解决递归筛选路由数组的问题
你现在的问题出在两个核心逻辑错误上:一是路由匹配的判断顺序不对,导致子路由被单独提取出来;二是处理子路由时的引用方式引发了循环引用和重复条目。咱们来一步步修正:
问题根源拆解
- 原代码会先判断当前路由的
path是否在menuRoutes里,匹配到就单独生成条目——但像userinfo这种子路由,它的父路由/user虽然不在menuRoutes里,但因为有符合条件的子路由,应该保留父路由并仅保留匹配的子路由,而不是把子路由单独拎出来。 - 原代码在处理子路由时,没有正确判断父路由是否需要保留,导致父路由和子路由都被重复添加,同时因为直接引用原对象的结构,引发了循环引用问题。
修改后的代码
const globalRoutes = [ { path: '/user', meta: { title: 'UserManager', icon: 'el-icon-user' }, children: [{ path: 'userinfo', meta: { title: 'UserInfo', } }, { path: 'roleinfo', meta: { title: 'Roleinfo' } }, { path: 'rolemenu', meta: { title: 'roleMenu' } } ] }, { path: '/test', meta: { title: 'TestMenu', icon: 'el-icon-setting' } } ] const menuRoutes = ['userinfo', '/test'] function filterRoutes(routes) { const res = [] for (const route of routes) { // 创建新对象存储当前路由的基础信息,避免修改原对象和循环引用 const currentRoute = { path: route.path, meta: { ...route.meta } } // 先递归处理子路由,拿到筛选后的子路由列表 let matchedChildren = [] if (route.children) { matchedChildren = filterRoutes(route.children) } // 判断当前路由是否需要保留的两个条件: // 1. 当前路由本身在menuRoutes中 // 2. 当前路由有匹配的子路由(子路由列表不为空) const isCurrentMatched = menuRoutes.includes(route.path) const hasValidChildren = matchedChildren.length > 0 if (isCurrentMatched || hasValidChildren) { // 只有存在有效子路由时,才添加children属性 if (hasValidChildren) { currentRoute.children = matchedChildren } res.push(currentRoute) } } return res } console.log(filterRoutes(globalRoutes))
关键修改点说明
- 先处理子路由再判断父路由:先递归筛选子路由,就能提前知道当前父路由是否有符合条件的子节点,避免把子路由单独提取出来。
- 明确路由保留规则:只要当前路由本身匹配,或者有匹配的子路由,就保留该路由,符合菜单的层级逻辑。
- 避免循环引用:每次处理都创建新的路由对象(而非直接引用原对象),并且仅在子路由筛选结果非空时才添加
children属性。 - 语义化判断:用
includes替代indexOf,代码更简洁易读。
运行结果
执行这段代码后,会得到你期望的正确输出:
[ { "path": "/user", "meta": { "title": "UserManager", "icon": "el-icon-user" }, "children": [ { "path": "userinfo", "meta": { "title": "UserInfo" } } ] }, { "path": "/test", "meta": { "title": "TestMenu", "icon": "el-icon-setting" } } ]
内容的提问来源于stack exchange,提问作者andylei
相关产品推荐
相关产品推荐

