JS递归遍历查询权限:处理异构权限树结构的解决方案

作者:小括号

时间:2026-10-25

浏览:149

本文介绍在基于qiankun的微前端项目中,针对层级结构中子菜单键名不一致(如children、functionList等)的权限树,设计并实现了一种基于do-while循环与递归思想结合的遍历算法。通过构建通用的查找模板findMap,利用数组filter方法逐层匹配,实现了对按钮级权限的高效查询,解决了传统递归难以应对异构数据结构的痛点。

文章目录

前言

近期参与了一个基于qiankun构建的大型微前端项目,该项目包含十余个子应用。在此背景下,基座侧独立开发了一套完善的权限中心模块。该权限体系采用了“模块 > 一级菜单 > N级菜单/按钮”的多层结构进行权限管理。

本次任务聚焦于其中一个子应用的按钮级权限控制。在鉴权环节,编写了一个辅助方法,旨在从复杂的权限树中查询特定按钮是否存在于用户的权限列表中,以此决定用户是否拥有该按钮的操作权限。

需求分析

  • 权限树中每一层级对应的子菜单键名并不统一。
  • 业务逻辑需要从权限树中准确获取是否存在指定权限。
  • 按钮级别的菜单名称可能存在重复情况。

设计思路

  • 通过对权限树的分析有如下结论:
    • 权限树的层级深度是有限的。
    • 由于子菜单对应的键名不一致,部分节点使用children,部分使用functionList,还有部分使用menuList。
    • 在同一层级内,菜单项不会重复。
  • 设计一种可遍历的数据结构,并对该结构执行遍历查找操作。
  • 若找到目标且数据结构一致则返回true,若在任意一级未找到则返回false。

代码

鉴于上述需求分析中提到的原因,传统的递归方法难以直接适用。因此,结合具体数据特征,构建了一种支持递归解决思路的数据结构。

此处采用do-while循环配合递归findMap模板的方式实现。之所以需要定义三个字段,是因为子菜单对应的键名各不相同。虽然理论上可以修改原始数据结构,但这会带来较大的改动成本和影响范围,因此采取当前方案。

声明查找模板如下

interface findItem {
    findKey: string   // 目标项的key
    findVal: string   // 目标项的value
    childrenKey: string   // 子菜单的key
}
// 查找模板
const findMap =  [
    {findkey: 'name', findVal: "模块A", childrenKey:'functionList'},
    {findkey: 'functionName', findVal: '菜单1', childrenKey:'children'},
    {findkey: 'functionName', findVal: '菜单1-1', childrenKey:'children'},
    {findkey: 'functionName', findVal: '按钮1-1-3'}
]

接下来执行递归findItem[]逻辑。

循环体内的查找方法有多种选择,此处临时选用数组的filter方法。实际上,数组的其他方法(如some、include等)也能实现类似结果。

js版本


/**
 * 查询是否存在 findMap 的结构数据
 * @param arr getJsonV2 接口返回的权限列表
 * @param findMap findItem[]
 * @result boolean
 */
const isAccessInDataByMap = (arr, findMap) => {
    let findList = arr // 重置查找范围
    let i= 0 // 初始值
    let tempArr = [] // 
    do {
        tempArr = findList.filter(item => item[findMap[i].findkey] === findMap[i].findVal)
        if(tempArr.length > 0){
            findList = tempArr[0][findMap[i].childrenKey]
            i++
        }else{
            return false
        }
    } while (i< findMap.length);
    if(tempArr.length && i === findMap.length){
        return true
    }
}

ts版本

// tool-is-has-access-in-data-by-map.ts
// 声明接口
export interface findItem {
    findKey: string
    findVal: string
    childrenKey: string
}
/**
 * 查询是否存在 findMap 的结构数据
 * @param arr getJsonV2 接口返回的权限列表
 * @param findMap findItem[]
 * @result boolean
 */
export const isAccessInDataByMap:(data:any, findMap:findItem[]) => boolean | undefined = (data:any, findMap:findItem[]) => {
    let findList = data   // 重置查找范围
    let i= 0        // 记录下标
    let tempArr = []
    do {
        tempArr = findList.filter((item: { [x: string]: string; }) => item[findMap[i].findKey] === findMap[i].findVal)
        if(tempArr.length > 0){
            findList = tempArr[0][findMap[i].childrenKey]
            i++
        }else{
            return false
        }
    } while (i< findMap.length);
    if(tempArr.length && i === findMap.length){
        return true
    }
};

后记

记录此方法的原因并非仅针对当前场景,更在于总结一种解决问题的思路。

通常的树状结构中,各层数据结构一致,仅最后一层无子元素,以此作为递归终止条件。而在本场景中,尽管各层数据结构相似,但用于核对的键值对却各不相同。因此,需要一把“尺子”来进行查找。

方法本身并不复杂,难点在于如何将其总结为通用解决方案,实现从0到1的突破,进而推广至从1到n的应用。

以上就是JS递归遍历查询是否有权限示例详解的详细内容,更多关于JS递归遍历查询权限的资料请关注本站其它相关文章!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章