js 遞歸json樹實(shí)現(xiàn)根據(jù)子id查父id的方法分析
本文實(shí)例講述了js 遞歸json樹實(shí)現(xiàn)根據(jù)子id查父id的方法。分享給大家供大家參考,具體如下:
最近做了一個(gè)類似用js實(shí)現(xiàn)思維導(dǎo)圖的功能,作為思維導(dǎo)圖,一定會(huì)有樹狀結(jié)構(gòu)的數(shù)據(jù)產(chǎn)生,在操作里面的節(jié)點(diǎn)時(shí)會(huì)經(jīng)常需要查找節(jié)點(diǎn) 的父節(jié)點(diǎn)及父節(jié)點(diǎn)。
對(duì)于未知層級(jí)的樹狀數(shù)據(jù),用for循環(huán)是無(wú)法實(shí)現(xiàn)的,因?yàn)椴恢酪h(huán)幾層,那么最合適的方法就是用js遞歸
界面結(jié)構(gòu):
json數(shù)據(jù):
"orgTreeData":{ "nodeId":"19A5B", "nodeName":"預(yù)分析用戶:1313.85萬(wàn)人", "nodeType":"root", "expand":true, "dataCnt":13138494, "children":[ { "nodeId":"19A5B_19A5C", "nodeName":"客戶狀態(tài)", "nodeType":"tag", "children":[ { "nodeId":"19A5B_19A5C_19A5E", "nodeName":"包含(實(shí)名制停機(jī),IPBUS帳戶封鎖停機(jī))", "dataCnt":"0人", "nodeType":"domain", "counted":2, "children":[ { "nodeId":"19A5B_19A5C_19A5E_19A67", "nodeName":"積分", "nodeType":"tag", "children":[ ], "expand":true, "counted":0, "condType":"1", "dataType":1, "propType":"1", "propSql":"", "labelId":"BLD00013", "linked":false, "linkedId":"" }, { "nodeId":"19A5B_19A5C_19A5E_19A68", "nodeName":"是否通信客戶", "nodeType":"tag", "children":[ ], "expand":true, "counted":0, "condType":"3", "dataType":1, "propType":"4", "propSql":"", "labelId":"BLD00010", "linked":false, "linkedId":"" } ], "expand":true, "expressType":"7", "expressValue1":[ "17", "14" ], "expressValue2":"", "expressValue3":"17##14", "expressValue4":"實(shí)名制停機(jī)##IPBUS帳戶封鎖停機(jī)", "expressValue5":"實(shí)名制停機(jī),IPBUS帳戶封鎖停機(jī)", "linked":false, "linkedId":"" }, { "nodeId":"19A5B_19A5C_19A60", "nodeName":"包含(營(yíng)業(yè)銷戶)", "dataCnt":"0人", "nodeType":"domain", "counted":2, "children":[ { "nodeId":"19A5B_19A5C_19A60_19A69", "nodeName":"入網(wǎng)歸屬地域", "nodeType":"tag", "children":[ { "nodeId":"19A5B_19A5C_19A60_19A69_19A6A", "nodeName":"包含(鄂爾多斯,阿盟)", "dataCnt":"", "nodeType":"domain", "counted":0, "children":[ ], "expand":true, "expressType":"7", "expressValue1":[ "477", "482" ], "expressValue2":"", "expressValue3":"477##482", "expressValue4":"鄂爾多斯##阿盟", "expressValue5":"鄂爾多斯,阿盟", "linked":false, "linkedId":"" } ], "expand":true, "counted":0, "condType":"2", "dataType":1, "propType":"3", "propSql":"1005", "labelId":"BLD00017", "linked":false, "linkedId":"" } ], "expand":true, "expressType":"7", "expressValue1":[ "40" ], "expressValue2":"", "expressValue3":"40", "expressValue4":"營(yíng)業(yè)銷戶", "expressValue5":"營(yíng)業(yè)銷戶", "linked":false, "linkedId":"" } ], "expand":true, "counted":0, "condType":"2", "dataType":1, "propType":"3", "propSql":"1002", "labelId":"BLD00004", "linked":false, "linkedId":"" }, { "nodeId":"19A5B_19A61", "nodeName":"全球通級(jí)別 && 全球通級(jí)別", "nodeType":"tag", "children":[ ], "expand":true, "counted":0, "condType":"2", "dataType":1, "propType":"3", "propSql":"1004", "labelId":"BLD00008", "linked":true, "linkedId":"19A5B_19A64" }, { "nodeId":"19A5B_19A62", "nodeName":"同證件號(hào)碼數(shù)量", "nodeType":"tag", "children":[ ], "expand":true, "counted":0, "condType":"1", "dataType":1, "propType":"1", "propSql":"", "labelId":"BLD00009", "linked":false, "linkedId":"" } ] }
我這個(gè)對(duì)象結(jié)構(gòu)是按nodeId匹配的,每個(gè)下級(jí)為children數(shù)組。
如果我想點(diǎn)擊任何一個(gè)節(jié)點(diǎn)根據(jù)節(jié)點(diǎn)nodeId得到它的父節(jié)點(diǎn)nodeId,就得把整個(gè)json樹遞歸遍歷一遍,知道找到這個(gè)節(jié)點(diǎn),從而得到它的父節(jié)點(diǎn)
關(guān)于遞歸,一定要掌握好結(jié)束條件,懂得何時(shí)return,不然會(huì)出現(xiàn)返回不出值或者循環(huán)提前結(jié)束的情況。
js代碼:
//傳入?yún)?shù):需要遍歷的json,需要匹配的id findPnodeId(data,nodeId){ //設(shè)置結(jié)果 let result; if (!data) { return;//如果data傳空,直接返回 } for (var i = 0; i < data.children.length; i++) { let item = data.children[i]; if (item.nodeId == nodeId) { result=data.nodeId; //找到id相等的則返回父id return result; } else if (item.children && item.children.length > 0) { //如果有子集,則把子集作為參數(shù)重新執(zhí)行本方法 result= findPnodeId(item, nodeId); //關(guān)鍵,千萬(wàn)不要直接return本方法,不然即使沒有返回值也會(huì)將返回return,導(dǎo)致最外層循環(huán)中斷,直接返回undefined,要有返回值才return才對(duì) if(result){ return result; } } } //如果執(zhí)行循環(huán)中都沒有return,則在此return return result; }
總之,遞歸相當(dāng)于上圖中的軌跡查找。
條件執(zhí)行到 需要 重新執(zhí)行 findPnodeId 方法的地方開始一頭扎進(jìn)去,如果第下一次執(zhí)行找到了符合條件的值,則return出來,返回上一層,下一層的 findPnodeId 方法結(jié)束,返回值,上一層的findPnodeId方法也就直接return結(jié)束了。
如果下一層方法 進(jìn)入循環(huán)第一次依然沒有找到 符合的值 ,如果還有子集,則會(huì)繼續(xù)向更下一層進(jìn)發(fā);就像上圖中的紅線,直到?jīng)]有子集才結(jié)束,所以千萬(wàn)不讓直接 在遞歸 findPnodeId 方法前直接return,也就是這樣:
else if (item.children && item.children.length > 0) { return findPnodeId(item, nodeId); }
這樣會(huì)使 json在第一條樹軌跡結(jié)束時(shí)(上圖中的紅色軌跡)如果找不到值 強(qiáng)制 retrun undefined,因?yàn)闆]一個(gè)方法都向上return,for循環(huán)中,一旦return,會(huì)直接打斷循環(huán),使方法結(jié)束,結(jié)果是最底層 的undefined 直接return到頂層,頂層直接將undefined return出來,根本沒有走第234條線,所以一定要先判斷一下是否返回值再return,像這樣:
} else if (item.children && item.children.length > 0) { result= this.findPnodeId(item, nodeId); if(result){ return result; } }
那么如果方法前不寫return會(huì)怎樣?
是方法無(wú)法return,依然無(wú)法遞歸
PS:關(guān)于json操作,這里再為大家推薦幾款比較實(shí)用的json在線工具供大家參考使用:
在線JSON代碼檢驗(yàn)、檢驗(yàn)、美化、格式化工具:
http://tools.jb51.net/code/json
JSON在線格式化工具:
http://tools.jb51.net/code/jsonformat
在線XML/JSON互相轉(zhuǎn)換工具:
http://tools.jb51.net/code/xmljson
json代碼在線格式化/美化/壓縮/編輯/轉(zhuǎn)換工具:
http://tools.jb51.net/code/jsoncodeformat
在線json壓縮/轉(zhuǎn)義工具:
http://tools.jb51.net/code/json_yasuo_trans
更多關(guān)于JavaScript相關(guān)內(nèi)容可查看本站專題:《JavaScript中json操作技巧總結(jié)》、《JavaScript查找算法技巧總結(jié)》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
- js中遞歸函數(shù)的使用介紹
- JavaScript的遞歸之遞歸與循環(huán)示例介紹
- JS遍歷數(shù)組和對(duì)象的區(qū)別及遞歸遍歷對(duì)象、數(shù)組、屬性的方法詳解
- JS中遞歸函數(shù)
- javascript如何用遞歸寫一個(gè)簡(jiǎn)單的樹形結(jié)構(gòu)示例
- JS遞歸遍歷對(duì)象獲得Value值方法技巧
- 深入Javascript函數(shù)、遞歸與閉包(執(zhí)行環(huán)境、變量對(duì)象與作用域鏈)使用詳解
- JavaScript采用遞歸算法計(jì)算階乘實(shí)例
- 關(guān)于JavaScript遞歸經(jīng)典案例題詳析
相關(guān)文章
JS將網(wǎng)址url轉(zhuǎn)化為JSON格式的方法
這篇文章主要介紹了JS將網(wǎng)址url轉(zhuǎn)化為JSON格式的方法,需要的朋友可以參考下2018-07-07Javascript實(shí)現(xiàn)鼠標(biāo)右鍵特色菜單
鼠標(biāo)右鍵大家都經(jīng)常操作,但是鼠標(biāo)的內(nèi)容是不是符合大家的“口味”?這篇文章就是教大家如何定制自己專屬鼠標(biāo)右鍵,需要的朋友可以參考下2015-08-08JavaScript高級(jí)程序設(shè)計(jì) 客戶端存儲(chǔ)學(xué)習(xí)筆記
JavaScript高級(jí)程序設(shè)計(jì) 客戶端存儲(chǔ)學(xué)習(xí)筆記,在客戶端用于存儲(chǔ)會(huì)話信息2011-09-09JavaScript如何攔截全局Fetch的請(qǐng)求與響應(yīng)詳解
全局的fetch()方法用于發(fā)起獲取資源的請(qǐng)求,它返回一個(gè)promise,這個(gè)promise會(huì)在請(qǐng)求響應(yīng)后被resolve,并傳回Response對(duì)象,這篇文章主要給大家介紹了關(guān)于JavaScript如何攔截全局Fetch的請(qǐng)求與響應(yīng)的相關(guān)資料,需要的朋友可以參考下2024-04-04JS Thunk 函數(shù)的含義和用法實(shí)例總結(jié)
這篇文章主要介紹了JS Thunk 函數(shù)的含義和用法,結(jié)合實(shí)例形式總結(jié)分析了JS Thunk 函數(shù)的具體含義、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04JS實(shí)現(xiàn)不用中間變量temp 實(shí)現(xiàn)兩個(gè)變量值得交換方法
這篇文章主要介紹了在JS中 實(shí)現(xiàn)不用中間變量temp 實(shí)現(xiàn)兩個(gè)變量值得交換 ,需要的朋友可以參考下2018-02-02js實(shí)現(xiàn)前端界面導(dǎo)航欄下拉列表
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)前端界面導(dǎo)航欄下拉列表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08