首頁 > 軟體

JS遞迴遍歷查詢是否有許可權範例詳解

2022-07-25 14:03:12

前言

最近參與了一個基於 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遞迴遍歷查詢許可權的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com