JS遞歸遍歷查詢是否有權限示例詳解
前言
最近參與瞭一個基於 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遞歸遍歷查詢權限的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- JS對象數組去重的3種方法示例及對比
- vue中el-checkbox全選、反選、多選的實現
- 淺談JS數組內置遍歷方法有哪些和區別
- 利用JS十分鐘判斷數組中存在元素的多種方式
- vue如何實現點擊選中取消切換