扁平化嵌套菜单权限的核心是提取符合条件的菜单项并补全路径信息。推荐用flatMap递归实现,支持过滤、透传fullPath/level/parentTitle,兼顾性能与可读性,同时注意空值防护和深度限制。

接口返回的嵌套菜单权限(如树形结构的 menuList,含 children 字段)需要扁平化过滤时,核心目标是:**提取所有符合条件的菜单项(比如 visible === true 且 permission 匹配当前角色),同时保持每个菜单项携带其完整路径信息(如父级名称、层级、路由前缀等),便于权限校验或侧边栏渲染。**
用 flatMap 递归提取 + 补全路径字段
这是最常用也最清晰的方式。不依赖外部库,纯原生 JavaScript,适合中等深度(≤5 层)的菜单结构。
- 对每一层菜单调用
flatMap,若存在children则递归处理,并把当前节点信息(如title、path)透传下去 - 每层递归中,为子项添加
fullPath(拼接父 path)、level、parentTitle等上下文字段 - 在递归入口处统一做过滤:只保留
visible: true的节点,避免无效遍历
示例代码:
function flattenMenu(menuList, options = {}) {
const { prefix = '', parentTitle = null, level = 0 } = options;
return menuList.flatMap(item => {
if (!item.visible) return []; // 过滤掉不可见项
const fullPath = prefix ? `${prefix}/${item.path}` : item.path;
const enriched = {
...item,
fullPath,
level,
parentTitle,
};
// 若有 children,递归处理并合并结果
if (Array.isArray(item.children) && item.children.length) {
return [enriched, ...flattenMenu(item.children, {
prefix: fullPath,
parentTitle: item.title,
level: level + 1,
})];
}
return [enriched];
});
}
// 使用
const flatMenus = flattenMenu(apiResponse.menuList);
// 返回一维数组,每个元素含 fullPath、level、parentTitle 等字段
用 flat() + 自定义映射函数批量补字段
当菜单结构已知较浅(如最多三层),且你更倾向函数式链式写法,可先用 flat(Infinity) 拍平,再用 map 补全路径和权限上下文。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 先用
flat(Infinity)得到所有叶子节点(但丢失父子关系) - 配合一个预构建的「路径映射表」——通过一次深度遍历生成
{ id: 'menu-2', fullPath: '/system/user', level: 2 }等缓存 - 再用
map关联补全,完成过滤与增强
优点是逻辑分离、可缓存映射表;缺点是需额外维护映射关系,不适合动态变更频繁的菜单。
结合 Set 去重 + 权限白名单快速过滤
如果后端返回的是“全量菜单”,而你只需保留当前用户有权限的若干项(比如只显示 permission 在 ['sys:user:list', 'sys:role:edit'] 中的菜单),推荐组合使用:
- 用
new Set(permissionList)构建 O(1) 查找的权限集 - 在
flatMap或递归过程中,用permissionSet.has(item.permission)直接判断 - 支持“或”逻辑(任一权限匹配即展示),“且”逻辑(需全部满足)也可扩展
这种写法性能高、语义明确,特别适合 RBAC 场景下的菜单动态裁剪。
注意嵌套中的数组安全与空值处理
真实接口数据常含空 children: null、undefined 或空数组,直接 .flatMap 可能报错或跳过。务必加防护:
- 用
Array.isArray(item.children) && item.children.length替代item.children?.length - 对
title、path等关键字段做默认值 fallback,如item.title ?? '未命名' - 避免
flat(Infinity)处理极深菜单(如 >10 层),可能触发栈溢出;此时应改用 while 循环 + 栈模拟递归

















