在前端開發中,有一種組件是每一個前端都繞不過去的,樹組件。在業務中像目錄結構、組織架構、行政區域劃分這些都是典型的樹組件使用場景。通常來講,前端也就是拿來一個封裝好的控件,而後傳入符合要求的數據結構就完事了。可是,有的時候咱們拿到的東西可能並不完美,好比服務端給咱們返回了一個列表,列表中每一項之間的父子關係經過id與parentId來肯定,那麼問題來了,咱們如何在前端把這樣的列表數據轉換成樹結構的數據呢?想過麼?作過麼?作得出來麼?
我搜索了一大圈,發現絕大部分都是把代碼一貼就完事,根本不講思路是什麼,爲了能一勞永逸的解決這個問題,我以爲先把思路理清是最重要的,至於怎麼實現,就是coding的問題了,coding就看每一個人心情了,每一個人都有本身喜歡的方式,我的不建議把coding寫死,僵化。javascript
需求是什麼?
前端
大概是這個樣子,應該一目瞭然了。java
先說一下總體思路,根據parentId和id把數組中的每一項的父節點找到,並將本身做爲父節點的children中的一項,全部的數據項都處理完畢後,其實就差很少了,最後咱們把根節點找到並返回,轉換完成。json
const List = [ {id: 1, name: 'child1', parentId: 0}, {id: 2, name: 'child2', parentId: 0}, {id: 6, name: 'child2_1', parentId: 2}, {id: 0, name: 'root', parentId: null}, {id: 5, name: 'child1_2', parentId: 1}, {id: 4, name: 'child1_1', parentId: 1}, {id: 3, name: 'child3', parentId: 0}, {id: 7, name: 'child3_1', parentId: 3} ] function ListToTree (list) { const copyList = list.slice(0) const tree = [] for (let i = 0;i < copyList.length;i++) { // 找出每一項的父節點,並將其做爲父節點的children for (let j = 0;j < copyList.length;j++) { if (copyList[i].parentId === copyList[j].id) { if (copyList[j].children === undefined) { copyList[j].children = [] } copyList[j].children.push(copyList[i]) } } // 把根節點提取出來,parentId爲null的就是根節點 if (copyList[i].parentId === null) { tree.push(copyList[i]) } } return tree } const tree = ListToTree(List) console.log(JSON.stringify(tree))
上面代碼直接扔到瀏覽器中便可運行,可自行看看結果。這裏先把結果放在下面,供參考。
[{"id":0,"name":"root","parentId":null,"children":[{"id":1,"name":"child1","parentId":0,"children":[{"id":5,"name":"child1_2","parentId":1},{"id":4,"name":"child1_1","parentId":1}]},{"id":2,"name":"child2","parentId":0,"children":[{"id":6,"name":"child2_1","parentId":2}]},{"id":3,"name":"child3","parentId":0,"children":[{"id":7,"name":"child3_1","parentId":3}]}]}]
以上結果放到https://www.bejson.com/jsoned...中查看,效果更佳。數組
列表轉樹的過程,我這裏用了兩層循環,而後利用了js的對象引用機制,將列表轉成了樹,其實這個過程當中已經改變了原有的列表數據結構(循環結束後打印copyList便可看到結果),因此在第一步的時候才先複製了一個列表進來。這裏應該還有可優化的地方,歡迎你們提供更多更好的思路,懇請在補充新的方案時,先把思路說清楚,切勿直接扔代碼上來。交流、溝通、理解效果纔好。瀏覽器