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