本文介绍如何通过递归遍历任意深度嵌套的路由数组,筛选出 visible: true 的节点,并将其完整路径(含父级前缀)与 title 组合成 Record 映射对象。
本文介绍如何通过递归遍历任意深度嵌套的路由数组,筛选出 `visible: true` 的节点,并将其完整路径(含父级前缀)与 `title` 组合成 `record
在现代前端路由系统中,菜单或导航结构常以树形嵌套方式组织,层级深度不确定(可能达 5 层甚至更深),且仅需展示 visible: true 的有效项。此时,需将扁平化的路径-标题映射(如 "/admin/settings/themes": "Theme")高效生成,供动态菜单渲染、权限校验或国际化路由匹配使用。
核心思路是:递归 + 路径累积 + 条件过滤。我们定义一个纯函数 buildStringRecord,接收三个参数:
- routes: 当前层级的路由数组;
- parentPath: 累积的父级路径(初始为空字符串);
- resultMap: 用于收集结果的可变对象(默认空对象,避免重复创建)。
每层遍历中,仅对 visible === true 的节点处理:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 拼接完整路径:const fullPath = parentPath + route.path;
- 若存在 title,则写入 resultMap[fullPath] = route.title;
- 若存在 children 数组,则递归调用自身,传入 fullPath + '/' 作为新父路径(注意末尾斜杠确保路径格式统一,如 /admin/ → /admin/dashboard)。
以下是完整、类型安全的 TypeScript 实现:
type RouteType = {
path: string;
visible: boolean;
title?: string;
index?: boolean;
children?: RouteType[];
};
function buildStringRecord(
routes: RouteType[],
parentPath: string = '',
resultMap: Record<string string> = {}
): Record<string string> {
for (const route of routes) {
if (route.visible) {
const fullPath = parentPath + route.path;
if (route.title !== undefined) {
resultMap[fullPath] = route.title;
}
if (Array.isArray(route.children) && route.children.length > 0) {
buildStringRecord(route.children, fullPath + '/', resultMap);
}
}
}
return resultMap;
}
// 使用示例
const routes: RouteType[] = [
{ path: '/user', visible: true, title: 'User' },
{
path: '/admin',
visible: true,
title: 'Admin',
children: [
{ index: true, visible: false },
{ path: 'dashboard', visible: true, title: 'Dashboard' },
{ path: 'changelog', visible: true, title: 'Changelog' },
{ path: 'profile', visible: true, title: 'Profile' },
{
path: 'settings',
visible: true,
title: 'Settings',
children: [
{ index: true, visible: false },
{ path: 'themes', visible: true, title: 'Theme' },
{ path: 'themes/new', visible: true, title: 'New' }
]
}
]
}
];
const resultMap = buildStringRecord(routes);
console.log(resultMap);
// 输出:
// {
// "/user": "User",
// "/admin": "Admin",
// "/admin/dashboard": "Dashboard",
// "/admin/changelog": "Changelog",
// "/admin/profile": "Profile",
// "/admin/settings": "Settings",
// "/admin/settings/themes": "Theme",
// "/admin/settings/themes/new": "New"
// }</string></string>
⚠️ 注意事项:
- 路径拼接逻辑:parentPath + route.path 不自动添加分隔符,因此递归时显式追加 '/',确保子路径格式正确(如 /admin/ + dashboard → /admin/dashboard);
- 空 title 安全:使用 route.title !== undefined 判断,避免 title: undefined 被错误写入;
- children 类型防护:增加 Array.isArray(route.children) 检查,防止运行时因 children: undefined 或非数组值导致崩溃;
- 不可变性权衡:该实现复用 resultMap 对象提升性能,若需纯函数行为(无副作用),可改为每次递归返回新对象合并(但对深层嵌套性能略低);
- TS 类型推导:建议明确定义 RouteType 接口,增强类型安全性与 IDE 支持。
此方案简洁、健壮、可扩展,适用于任意深度嵌套结构,是处理动态路由元数据的标准实践之一。










