JavaScript遞歸操作樹形結(jié)構(gòu)代碼示例
樹形結(jié)構(gòu)轉(zhuǎn)成扁平結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu)
let data = [ { name: "1", children: [{ name: "3" }, { name: "4" }] }, { name: "2", children: [{ name: "5" }, { name: "6", children: [{name: "7"}] }] } ]
轉(zhuǎn)成扁平化
function dataTree(data) { let result = []; for (const item of data) { // result.push(item) result.push({ name: item.name }) // 只取當(dāng)前節(jié)點(diǎn)的信息,不包括 children if (item.children === null || item.children === undefined) { continue; } let getChildren = dataTree(item.children) result = result.concat(getChildren) } return result } console.log("原數(shù)組結(jié)構(gòu)", data); console.log("扁平化的對象", dataTree(data));
運(yùn)行結(jié)果
扁平結(jié)構(gòu)轉(zhuǎn)成樹形結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu)
let datas = [ {id: 1, name: 1, parentId: null}, {id: 2, name: 2, parentId: 1}, {id: 3, name: 3, parentId: 1}, {id: 4, name: 4, parentId: null}, {id: 5, name: 5, parentId: 4}, {id: 6, name: 6, parentId: 4}, {id: 7, name: 7, parentId: 6}, {id: 8, name: 8, parentId: 6}, ]
轉(zhuǎn)成樹形結(jié)構(gòu)
function dataList(data){ let map = {}; for(let item of data){ map[item.id] = item } let result = []; //存放數(shù)組 for(let item of data){ item.children = []; //給每個(gè)數(shù)組添加一個(gè)空children if(item.parentId === null){ result.push(item)//最上級的標(biāo)簽 }else{ //相當(dāng)于用這個(gè) parentId 當(dāng)做父Id去查找對比查找數(shù)據(jù) let parent = map[item.parentId] //添加到剛剛定義children數(shù)組中去 parent.children.push(item) } } return result; } console.log("扁平化轉(zhuǎn)換成樹形結(jié)構(gòu):"); console.log("原數(shù)組結(jié)構(gòu)",datas); console.log("樹形結(jié)構(gòu)",dataList(datas));
運(yùn)行結(jié)果
根據(jù) parentId 查詢對應(yīng)的上級所有父節(jié)點(diǎn)
數(shù)據(jù)結(jié)構(gòu)
const data = [ { id: 1, parentId: undefined, name: 'TEST 1', children: [ { id: 5, parentId:1, name: 'TEST 5', children: [ { id: 10, parentId:4, name: 'TEST 10' }, { id: 11, parentId:4, name: 'TEST 11' } ] } ] }, { id: 2, parentId: undefined, name: 'TEST 2', children: [ { id: 6, parentId:2, name: 'TEST 6' }, { id: 7, parentId:2, name: 'TEST 7' } ] }, { id: 3, parentId: undefined, name: 'TEST 3', children: [ { id: 8, parentId:3, name: 'TEST 8' }, { id: 9, parentId:3, name: 'TEST 9' } ] }, { id: 4, name: 'TEST 4', children: [ ] } ]
根據(jù)parentId查找父節(jié)點(diǎn)
/** * * @param list 最外層傳入的數(shù)組 也可以是 this.數(shù)組 * @param parentId 子節(jié)點(diǎn)對應(yīng)的上級關(guān)系parentId * @returns {*[]} */ function findP(list,parentId){ const result = [] /** * 處理邏輯 * @param arr 要對比的數(shù)組 * @param parentId 傳遞進(jìn)來數(shù)據(jù)要對比父id(相當(dāng)于parentId) */ let forFn = function (arr,parentId){ for (let i = 0; i < arr.length; i++) { let item = arr[i]; if (item.id === parentId){ result.push(item) // console.log("遞歸數(shù)據(jù)",item) // console.log("遞歸id",item.parentId) forFn(list,item.parentId) break }else { if (item.children){ forFn(item.children,parentId) } } } } forFn(list,parentId); return result; } console.log("數(shù)據(jù)結(jié)構(gòu)==",data) console.log("查詢父類==",findP(data,11))
運(yùn)行結(jié)果(會把自己及父節(jié)點(diǎn)保存下來)
項(xiàng)目中運(yùn)用到的(僅供參考)
需求:根據(jù)點(diǎn)擊子節(jié)點(diǎn)查詢沒有就一直向上查
思路:拿到樹形結(jié)構(gòu)數(shù)組直接遞歸查詢
難點(diǎn):
1)獲取懶加載的樹形結(jié)構(gòu),(因?yàn)閼屑虞d封裝的數(shù)據(jù)結(jié)構(gòu)是分開裝的)
2)拼接成樹形結(jié)構(gòu)在處理
下面為實(shí)現(xiàn)例子 只列出大概實(shí)現(xiàn)思路
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>悲傷敵敵畏</title> </head> <body> <script type="text/javascript"> /** 分析: 1.獲取樹節(jié)點(diǎn)的數(shù)據(jù), 2.因?yàn)槭莑ist結(jié)構(gòu)的,先存放在map里面(遞歸) 3.拼接成層級數(shù)據(jù) 返回(遞歸) 4.根據(jù)parentId 查詢父級(遞歸) */ const data = [ { childNodes: [ {childNodes: [{childNodes:[],data:{id: 5, name: "測試5", parentId: 3}}], data: {id: 3, name: "測試3", parentId: 1}}, {childNodes: [], data: {id: 4, name: "測試4", parentId: 1}} ], data: {id: 1, name: "測試1", parentId: null} }, { childNodes: [], data: {id: 2, name: "測試2", parentId: null} }, ]; console.info("要處理的數(shù)據(jù)結(jié)構(gòu) >>>",data) //使用函數(shù) forChildren(data) function forChildren(list){ //TODO 轉(zhuǎn)成map結(jié)構(gòu),用于比較 let map = {}; let forMap = function (arr){ for (const item of arr) { map[item.data.id] = item.data if (item.childNodes.length > 0){ forMap(item.childNodes) } } } forMap(list) console.log("封裝的map >>>",map) //TODO 拼接成層級數(shù)據(jù): let result = []; let forList =function(arr){ for (const item of arr) { item.data.children = [] //為每個(gè)data添加一個(gè)數(shù)組 if (item.data.parentId === null){ //判斷是否為最外層(最外層一般都是空或者-1) result.push(item.data) } if (item.childNodes.length > 0){ for (const children of item.childNodes) { let paren = map[children.data.parentId] paren.children.push(children.data) forList(item.childNodes) } } } } forList(list) console.log("拼接好的樹形結(jié)構(gòu)",result) //TODO 根據(jù)子節(jié)點(diǎn)查找上面的每個(gè)父節(jié)點(diǎn) let parents = [] let forParent = function (arr,parentId){ for (const item of arr) { if (item.id === parentId){ parents.push(item) forParent(result,item.parentId) break }else { if (item.children){ forParent(item.children,parentId) } } } } forParent(result,5) console.log("父級以及自己的數(shù)據(jù)",parents) } </script> </body> </html>
總結(jié)
到此這篇關(guān)于JavaScript遞歸操作樹形結(jié)構(gòu)的文章就介紹到這了,更多相關(guān)js遞歸操作樹形結(jié)構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jQuery鼠標(biāo)懸浮鏈接彈出跟隨圖片實(shí)例代碼
這篇文章主要介紹了jQuery鼠標(biāo)懸浮鏈接彈出跟隨圖片實(shí)例代碼,需要的朋友可以參考下2016-01-01利用js制作html table分頁示例(js實(shí)現(xiàn)分頁)
這篇文章主要介紹了利用js制作html table的分頁示例(js實(shí)現(xiàn)分頁),需要的朋友可以參考下2014-04-04JavaScript canvas繪制圓形加載進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了JavaScript canvas繪制圓形加載進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06javascript實(shí)現(xiàn)tab切換特效
這篇文章主要介紹了javascript實(shí)現(xiàn)tab切換特效,實(shí)現(xiàn)的方法很簡單,特別適合初學(xué)者學(xué)習(xí)javascript實(shí)現(xiàn)tab切換特效,tab切換再也不是問題,需要的朋友可以參考下2015-11-11JavaScript進(jìn)階知識點(diǎn)作用域詳解
這篇文章主要介紹了JavaScript進(jìn)階講解一作用域,主要包括作用域、函數(shù)、閉包、面向?qū)ο?、ES新特性、事件循環(huán)、微任務(wù)、宏任務(wù)、內(nèi)存管理、Promise、await、?asnyc、防抖、節(jié)流等等知識點(diǎn),需要的朋友可以參考下2022-05-05