摘要:背景之前寫了一篇列表轉樹的文章,有列表轉樹的需求自然就會有樹轉列表的需求,這里我把樹轉列表的思路與代碼再整理一下。總結樹轉列表過程中,我這里的深度優先采用了遞歸方式,可能會對內存占用較多,使用時請自行權衡。
背景
之前寫了一篇列表轉樹的文章,有列表轉樹的需求自然就會有樹轉列表的需求,這里我把樹轉列表的思路與代碼再整理一下。
思路分析需求是什么?
老規矩,上圖
先說一下整體思路,就是遍歷樹中的每一個節點,在遍歷過程中要把節點的父節點id記錄下來,并作為該節點的parentId屬性值(保留層級關系,后續根據這個parentId和節點的id可以轉回樹結構),然后把該節點存入一個列表中。遍歷過程完成,也就實現了把樹結構轉換成了列表結構。
樹的遍歷方式有兩種,一種是深度優先遍歷,一種是廣度優先遍歷,這兩種方式思路如下圖所示:
廣度優先:
深度優先
思路看這兩個圖應該理得清楚了
我這里深度優先遍歷采用了遞歸的方式,然后廣度優先遍歷采用了循環的方式。
先說深度優先吧:
從第一層開始遍歷,遍歷該層中所有節點,為每一個遍歷到的節點添加上parentId屬性,存入結果列表。
每一個遍歷節點存入結果列表后,檢測該節點是否存在子節點,如果存在,則將子節點作為數據源重復第一步
當所有的節點都處理完成后,整個樹結構也就完成了轉化
再說說廣度優先:
從第一層開始遍歷,遍歷該層中所有節點,為每一個遍歷到的節點添加上parentId屬性,存入結果列表。
每一個遍歷節點存入結果列表后,檢測該節點是否存在子節點,如果存在,則將子節點數據項push到第一層遍歷的列表中(這里相當于在for循環的過程中,修改了被遍歷的數組的內容,在循環過程中把它變長了)
當所有的節點都處理完成后,整個樹結構也就完成了轉化
代碼深度優先
/* * 深度優先遍歷樹 * 一個遞歸方法 * @params tree:要轉換的樹結構數據 * @params list:保存結果的列表結構數據,初始傳[] * @params parentId:當前遍歷節點的父級節點id,初始為null(因為根節點無parentId) * */ function toListDF (tree, list, parentId = null) { for (let node of tree) { list.push({ id: node.id, name: node.name, children: [], parentId }) if (node.children.length !== 0) { toList(node.children, list, node.id) } } }
廣度優先:
/* * 廣度優先遍歷樹 * 一層循環 * @params tree:要轉換的樹結構數據 * @output list:返回轉換好的列表結構數據 * */ function toListBF (tree) { const tempList = tree.slice(0) const res = [] for (let node of tempList) { // 向結果中push每一個節點的數據 res.push({ id: node.id, name: node.name, children: [], parentId: node.parentId === undefined ? null : node.parentId }) // 如果該節點還有子節點,那么將子節點追加到待循環列表的后面 if (node.children.length !== 0) { // 這里注意,push的是children里面的項 tempList.push(...node.children.map((item) => { // 這里給每一項加上parentId item.parentId = node.id return item })) } } return res }
這里給一個簡單的樹結構數據用來測試
const tree = [ { id: 0, name: "root", children: [ { id: 1, name: "child1", children: [ { id: 4, name: "child1-1", children: [] }, { id: 5, name: "child1-2", children: [] } ] }, { id: 2, name: "child2", children: [ { id: 6, name: "child2-1", children: [ { id: 8, name: "child2-1-1", children: [] } ] } ] }, { id: 3, name: "child3", children: [ { id: 7, name: "child3-1", children: [] } ] } ] } ]
上面代碼直接扔到瀏覽器中即可運行,可自行看看結果。
總結樹轉列表過程中,我這里的深度優先采用了遞歸方式,可能會對內存占用較多,使用時請自行權衡。
在廣度優先的方式中,只用了一層循環,這里有一個核心的點,就是js在循環列表過程中,被循環的列表是可以修改的,比如push一個數據項,這樣會讓for循環多運行一次,這個點理解之后,我這里的廣度優先遍歷樹的方法就好理解了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95466.html
摘要:菜單顯示根據當前用戶的菜單數據顯示相應菜單權限埋點通過實現只支持控制顯示隱藏操作,報錯等需要自己實現 管理模塊參考界面:http://demo.jeesite.com/js/a/... 菜單管理 列表頁只實現增、刪、改 showImg(https://segmentfault.com/img/bVbjeKu?w=1700&h=512); 新增菜單:去除歸屬模塊字段,其他不變 showI...
摘要:源碼解析這邊解析的是從樹轉換成函數部分的源碼,由于第一次提交的源碼這部分不全,故做了部分更新,代碼全在文件夾中。入口整個語法樹轉函數的起點是文件中的函數明顯看到,函數傳入參數為語法樹,內部調用函數開始解析根節點容器節點。 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續寫: 模版字符串轉AST語法樹 AST語法樹轉r...
摘要:源碼解析這邊解析的是從樹轉換成函數部分的源碼,由于第一次提交的源碼這部分不全,故做了部分更新,代碼全在文件夾中。入口整個語法樹轉函數的起點是文件中的函數明顯看到,函數傳入參數為語法樹,內部調用函數開始解析根節點容器節點。 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續寫: 模版字符串轉AST語法樹 AST語法樹轉r...
摘要:最近在優化一段代碼,前端使用的是,頁面中有一個樹形菜單。我想的方法比較直接,一次性查出所有數據,減少查庫的頻率,畢竟數據量也就那么多條。 最近在優化一段代碼,前端使用的是Ext3,頁面中有一個樹形菜單。把項目放在本地跑,加載這個樹形菜單的速度似乎還湊合,但是在正式環境中點開這個頁面,這個樹形菜單加載的就很慢了,很明顯的感覺到卡殼了一下,于是去查看項目代碼,大致思路是這樣的,如下: 通過...
閱讀 2562·2021-11-22 12:05
閱讀 3447·2021-10-14 09:42
閱讀 1679·2021-07-28 00:15
閱讀 1987·2019-08-30 11:08
閱讀 1483·2019-08-29 17:31
閱讀 926·2019-08-29 16:42
閱讀 2335·2019-08-26 11:55
閱讀 2115·2019-08-26 11:49