工具函式:普通陣列如何轉為樹形結構資料(多層級)陣列?

夢裡夢一發表於2018-10-21

前言

最近一直在做的是一個後臺管理系統,更偏向於對資料的一個處理.其中最典型的資料處理,就是樹形結構資料,比如用在側邊欄選單,比如去描述各部門之間的上下級關係等等.有的時候後端勤快一點,把它處理了,但是萬一沒有呢?那就需要前端去處理嘍!另外補一句:坑爹的win10系統,又浪費了朕半天時間去重新配置環境.

第一種方案

技術點:物件導向,遞迴函式

可以用json-server外掛去簡單搭建一個伺服器,提供資料支撐

程式碼如下:(基於vue技術棧,iview-ui框架的tree元件的一個工具函式)

// 該模組用於將普通陣列去轉化為樹形結構的陣列結構
// 匯出一個建構函式,所以在使用的時候,要new一個物件
export function TreeData (a) {
  // 若a為空,tree即為空陣列,否則即為獲取的陣列資料
  this.tree = a || [];
  this.groups = {};
}
TreeData.prototype = {
  init: function (parentid) {
    // parentid的值在元件中被定義為0
    this.group();
    // 此時this.groups每一個parentid也只有一個子元素
    return this.getDom(this.groups[parentid]);
  },
  group: function () {
    // 該函式將普通陣列處理成二級結構,屬性名為父部門id,屬性值為子部門的部門資訊(資料形式為物件)
    // 每一個擁有子部門的父部門id都將作為this.groups的屬性名
    for (var i = 0; i < this.tree.length; i++) {
      if (this.groups[this.tree[i].parentid]) {
        // 目前資料中每一個部門的部門資訊中parentid都是存在的,寫一個if分歧應該是為了防止後端資料的失誤
        // 父級已經存在,使得同一級的子級能夠被追加進去
        this.groups[this.tree[i].parentid].push(this.tree[i]);
      } else {
        // 陣列元素的parentid值去做了groups的屬性名,parentid實際上是數字呀,就是要將子集資料追加到父集
        // this.groups物件是沒有屬性的,所有的parentid都將作為this.groups的屬性值
        this.groups[this.tree[i].parentid] = [];
        this.groups[this.tree[i].parentid].push(this.tree[i]);
      }
    }
  },
  // 非常任性,使用了函式遞迴,手法近似於深拷貝,物件才能一層一層的放下去
  getDom: function (a) {
    // a即為this.groups的屬性物件,如果不存在就返回為空,即後臺返回的資料為空的時候
    if (!a) {
      return '';
    }
    // 重新拼接出了一個JSON字串,所需要的樹形資料結構的字串形式,且有序排列
    // this.groups僅僅提供了一個擁有兩個層級的資料結構
    var data = '[';
    for (let i = 0; i < a.length; i++) {
      // this.groups[parentid]裡面的物件在group函式中被有序追加
      // "expand":"true","type":"department"的新增是出於iview的tree控制元件和專案其他地方的需要
      data += `{"title":"${a[i].departmentname}","departmentid":"${a[i].departmentid}","parentid":"${a[i].parentid}","expand":"true","type":"department"`;
      // 以第一次進入該函式為例
      // 因為有parentid為0的存在,所以部門裡我更願意增加一個0級部門
      // 如果一級部門還有子部門,就接著拼接children屬性值
      data += this.getDom(this.groups[a[i].departmentid]) ? ',' : '';
      // 將二級部門追加到一級部門的children屬性中
      data += this.getDom(this.groups[a[i].departmentid]) ? '"children":' + this.getDom(this.groups[a[i].departmentid]) : '';
      if (i === a.length - 1) {
        // 同層級的資料被新增完成
        data += '}';
      } else {
        data += '},';
      }
    };
    data += ']';
    return data;
  }
};
複製程式碼

要處理的資料:

{
  "msg": "success",
  "code": 200,
  "data": [
    {
      "departmentid": 1,
      "departmentname": "總部",
      "parentid": 0,
      "isrmv": false,
      "sort": 1,
      "leaderid": null,
      "qxDepartmentid": 1
    },
    {
      "departmentid": 2,
      "departmentname": "總經辦",
      "parentid": 1,
      "isrmv": false,
      "sort": 1,
      "leaderid": 44220,
      "qxDepartmentid": null
    },
    {
      "departmentid": 4,
      "departmentname": "IT部",
      "parentid": 1,
      "isrmv": false,
      "sort": 3,
      "leaderid": null,
      "qxDepartmentid": null
    },
    {
      "departmentid": 9,
      "departmentname": "技術組",
      "parentid": 1,
      "isrmv": false,
      "sort": null,
      "leaderid": null,
      "qxDepartmentid": 1432010565
    },
    {
      "departmentid": 10,
      "departmentname": "財務部",
      "parentid": 1,
      "isrmv": false,
      "sort": null,
      "leaderid": null,
      "qxDepartmentid": 1432014225
    },
    {
      "departmentid": 28,
      "departmentname": "總經辦22",
      "parentid": 1,
      "isrmv": false,
      "sort": null,
      "leaderid": null,
      "qxDepartmentid": null
    },
    {
      "departmentid": 31,
      "departmentname": "技術組1",
      "parentid": 4,
      "isrmv": false,
      "sort": null,
      "leaderid": null,
      "qxDepartmentid": null
    },
    {
      "departmentid": 32,
      "departmentname": "啦啦",
      "parentid": 4,
      "isrmv": false,
      "sort": null,
      "leaderid": null,
      "qxDepartmentid": null
    },
    {
      "departmentid": 33,
      "departmentname": "test23",
      "parentid": 1,
      "isrmv": false,
      "sort": null,
      "leaderid": null,
      "qxDepartmentid": 33
    },
    {
      "departmentid": 38,
      "departmentname": "測試部門3",
      "parentid": 1,
      "isrmv": false,
      "sort": null,
      "leaderid": 44229,
      "qxDepartmentid": 1432014228
    },
    {
      "departmentid": 39,
      "departmentname": "測試部門31",
      "parentid": 38,
      "isrmv": false,
      "sort": null,
      "leaderid": 44283,
      "qxDepartmentid": 1432014229
    },
    {
      "departmentid": 40,
      "departmentname": "測試部門32",
      "parentid": 38,
      "isrmv": false,
      "sort": null,
      "leaderid": 44246,
      "qxDepartmentid": 1432014230
    },
    {
      "departmentid": 41,
      "departmentname": "測試部門311",
      "parentid": 39,
      "isrmv": false,
      "sort": null,
      "leaderid": 44239,
      "qxDepartmentid": 1432014231
    },
    {
      "departmentid": 44,
      "departmentname": "測試部門34",
      "parentid": 38,
      "isrmv": false,
      "sort": null,
      "leaderid": null,
      "qxDepartmentid": 1432014233
    }
  ]
}
複製程式碼

處理後的資料:(expand是iview-ui的tree元件決定節點是否展開的一個欄位)


[
    {
        "children": [
            {
                "children": [],
                "departmentid": "2",
                "expand": "true",
                "parentid": "1",
                "title": "總經辦",
                "type": "department"
            },
            {
                "children": [
                    {
                        "departmentid": "31",
                        "expand": "true",
                        "parentid": "4",
                        "title": "技術組1",
                        "type": "department"
                    },
                    {
                        "departmentid": "32",
                        "expand": "true",
                        "parentid": "4",
                        "title": "啦啦",
                        "type": "department"
                    }
                ],
                "departmentid": "4",
                "expand": "true",
                "parentid": "1",
                "title": "IT部",
                "type": "department"
            },
            {
                "departmentid": "9",
                "expand": "true",
                "parentid": "1",
                "title": "技術組",
                "type": "department"
            },
            {
                "departmentid": "10",
                "expand": "true",
                "parentid": "1",
                "title": "財務部",
                "type": "department"
            },
            {
                "departmentid": "28",
                "expand": "true",
                "parentid": "1",
                "title": "總經辦22",
                "type": "department"
            },
            {
                "departmentid": "33",
                "expand": "true",
                "parentid": "1",
                "title": "test23",
                "type": "department"
            },
            {
                "children": [
                    {
                        "children": [
                            {
                                "departmentid": "41",
                                "expand": "true",
                                "parentid": "39",
                                "title": "測試部門311",
                                "type": "department"
                            }
                        ],
                        "departmentid": "39",
                        "expand": "true",
                        "parentid": "38",
                        "title": "測試部門31",
                        "type": "department"
                    },
                    {
                        "departmentid": "40",
                        "expand": "true",
                        "parentid": "38",
                        "title": "測試部門32",
                        "type": "department"
                    },
                    {
                        "departmentid": "44",
                        "expand": "true",
                        "parentid": "38",
                        "title": "測試部門34",
                        "type": "department"
                    }
                ],
                "departmentid": "38",
                "expand": "true",
                "parentid": "1",
                "title": "測試部門3",
                "type": "department"
            }
        ],
        "departmentid": "1",
        "expand": "true",
        "parentid": "0",
        "title": "總部",
        "type": "department"
    }
]
複製程式碼

最終的效果圖

工具函式:普通陣列如何轉為樹形結構資料(多層級)陣列?

第二種方案

關鍵字 id,parentId ,child

判斷是root節點的方法為 parentId===0

        let data = [
        {id: 1, text: 't11', parentId: 0},
        {id: 2, text: 't11', parentId: 0},
        {id: 3, text: 't11', parentId: 1},
        {id: 4, text: 't11', parentId: 1},
        {id: 5, text: 't11', parentId: 3},
        {id: 6, text: 't11', parentId: 2},
        ];
        data.forEach(ele => {
            // 第一次forEach遍歷到所有的陣列物件,不做去重,陣列依舊擁有6個元素
        let parentId = ele.parentId;
        if (parentId === 0) {
            //是根元素的hua ,不做任何操作,如果是正常的for-i迴圈,可以直接continue.
        } else {
            //如果ele是子元素的話 ,把ele扔到他的父親的child陣列中.它的父元素也可能是別人的子元素
            //遍歷6遍,陣列依舊擁有6個元素,只不過有些有巢狀關係
            data.forEach(d => {
            if (d.id === parentId) {
                let childArray = d.child;
                // 一則避免了去給d.child宣告定義空陣列
                // childArray為undefined時,用push方法去報undefined.push的錯
                if (!childArray) {
                    childArray = []
                }
                // 用push保證同級別的物件有序追加
                childArray.push(ele);
                d.child = childArray;
            } //else的地方不做處理,保證了最深層的物件沒有child屬性
            })
        }
        });
        //去除重複元素
        data = data.filter(ele => ele.parentId === 0);
        console.log('最終等到的tree結構資料: ', data);
複製程式碼

相關文章