JavaScript將具備父子關係的原始數據格式化成樹形結構數據(id,pid)

前幾天遇到一個樹型組件(相似樹形菜單)數據格式化的問題,因爲後臺把原始查詢的數據直接返回給前端,父子關係並未構建,所以須要前端JS來完成,後臺返回的數據和下面的測試數據類似。前端

1 var data=[
2 {id:1,pid:0,text:'A'},
3 {id:2,pid:4,text:"E[父C]"},
4 {id:3,pid:7,text:"G[父F]"},
5 {id:4,pid:1,text:"C[父A]"},
6 {id:5,pid:6,text:"D[父B]"},
7 {id:6,pid:0,text:'B'},
8 {id:7,pid:4,text:"F[父C]"}
9 ];

咱們能夠發現上面的測試數據有幾個特色,父節點與子節點不是順序排列的,也就是說按照id的順序,並非先有父節點,而後有下面的子節點,順序是混亂的,再就是父子層級有不少,這裏是3層。總結爲:順序混亂,層級未知。數組

若是是順序排列,層級固定,能夠投機取巧,寫法相對簡單,可是這裏偏偏相反。所以給格式化形成了必定的困難,當遇到層級未知的時候,通常都會想到遞歸的寫法,這裏我感受用遞歸也很差作,所以我也就沒有向這方面去深刻思考,這裏就也不作多的說明。測試

那麼個人作法比起遞歸來說更容易理解,先看下代碼。spa

 1 function toTreeData(data){
 2     var pos={};
 3     var tree=[];
 4     var i=0;
 5     while(data.length!=0){
 6         if(data[i].pid==0){
 7             tree.push({
 8                 id:data[i].id,
 9                 text:data[i].text,
10                 children:[]
11             });
12             pos[data[i].id]=[tree.length-1];    
13             data.splice(i,1);
14             i--;
15         }else{
16             var posArr=pos[data[i].pid];
17             if(posArr!=undefined){
18                 
19                 var obj=tree[posArr[0]];
20                 for(var j=1;j<posArr.length;j++){
21                     obj=obj.children[posArr[j]];
22                 }
23 
24                 obj.children.push({
25                     id:data[i].id,
26                     text:data[i].text,
27                     children:[]
28                 });
29                 pos[data[i].id]=posArr.concat([obj.children.length-1]);
30                 data.splice(i,1);
31                 i--;
32             }
33         }
34         i++;
35         if(i>data.length-1){
36             i=0;
37         }
38     }
39     return tree;
40 }

前面的測試數據通過上面代碼中的方法格式化後以下:code

[
    {
        "id": 1,
        "text": "A",
        "children": [
            {
                "id": 4,
                "text": "C[父A]",
                "children": [
                    {
                        "id": 7,
                        "text": "F[父C]",
                        "children": [
                            {
                                "id": 3,
                                "text": "G[父F]",
                                "children": []
                            }
                        ]
                    },
                    {
                        "id": 2,
                        "text": "E[父C]",
                        "children": []
                    }
                ]
            }
        ]
    },
    {
        "id": 6,
        "text": "B",
        "children": [
            {
                "id": 5,
                "text": "D[父B]",
                "children": []
            }
        ]
    }
]

原理很簡單,使用一個死循環來遍歷數組,循環跳出的條件是數組的長度爲0,也就是說,循環內部會引發數組長度的改變。這裏就幾個關鍵點作一下說明。blog

  1. 爲何要用死循環?順序混亂,若是單次循環,子節點出如今父節點以前,子節點很差處理,這裏作一個死循環至關於先把父節點所有找出,可是這裏又不是簡單的先把全部的父節點找出,找的同時,若是這個節點父節點已經找到,那麼能夠繼續作後續操做;
  2. 如何創建層級關係?代碼中有一個變量pos,這個用於保存每一個已添加到tree中的節點在tree中位置信息,好比上面測試數據父節點A添加到tree後,那麼pos中增長一條數據,pos={」1「:[0]},1就是父節點A的id,這樣寫便於查找,[0]表示父節點A在tree的第一個元素,即tree[0],若是某個位置信息爲[1,2,3],那麼表示這個節點在tree[1].children[2].children[3],這裏的位置關係其實就是父子的層級關係。

上面的測試數據的pos信息以下:遞歸

1 {
2     "1":[0],
3     "2":[0,0,1],
4     "3":[0,0,0,0],
5     "4":[0,0],
6     "5":[1,0],
7     "6":[1],
8     "7":[0,0,0]
9 }
相關文章
相關標籤/搜索