禿頭筆記1——樹狀對象

在平時的開發中,咱們常常會遇到樹狀對象的問題,例如:多級菜單、多級部門、多級文件夾等。通常狀況下,咱們在數據庫中會把這些信息存成平面結構,每一條數據之間有關聯字段,例如parentId和id。前端

一般的前端樹組件中會要求咱們傳入一個樹狀對象,可是在數據庫中存儲的都是平面結構的對象(簡稱平面對象),這就須要咱們將現有的數據結構進行組裝。服務器的資源是寶貴的,因此咱們應該儘量的將這一部分工做交至前端來完成。因而我寫了這麼一段代碼,但願對你們有所幫助,若是有什麼不正確的地方,歡迎指正。數據庫

/**
     * @conf childrenTag        子集合字段名,默認children
     * @conf keyMap.id          節點惟一標識字段名,默認id
     * @conf keyMap.parentId    父節點惟一標識字段名,默認parentId
     *
     * @method toSingle         樹狀對象轉平面對象
     * @method toList           平面對象轉樹狀對象
     */
    window.treeUtil = {
        childrenTag: 'children',
        keyMap: {id: 'id', parentId: 'parentId'},
        toSingle: function (obj) {
            if (obj instanceof Array) {
                var result = [];
                for (var i in obj) {
                    result.push(obj[i]);
                    if (obj[i][this.childrenTag]) {
                        result = result.concat(this.toSingle(obj[i][this.childrenTag]));
                        delete obj[i][this.childrenTag];
                    }
                }
                return result;
            } else if (obj instanceof Object) {
                return obj;
            } else {
                throw Error('It not is a Array or Object.');
            }
        },
        toList: function (arr) {
            // 查詢根節點
            var temp = this.findRootList(arr);
            return this.findChildList(temp.rootNds, temp.otherNds);
        },
        findChildList: function (rootNds, childNds) {
            for (var i in rootNds) {
                var recordIndex = [];
                rootNds[i][this.childrenTag] = [];
                for (var j in childNds) {
                    if (childNds[j][this.keyMap.parentId] === rootNds[i][this.keyMap.id]) {
                        rootNds[i][this.childrenTag].push(childNds[j]);
                        recordIndex.push(j);
                    }
                }
                // 儘量的刪去已經使用過的對象,用來減小遞歸時的循環次數。
                // 這裏爲了避免讓數組長度影響循環,從大到小遍歷
                for (var k = recordIndex.length - 1; k >= 0; k--) {
                    childNds.splice(recordIndex[k], 1);
                }
                if (childNds.length > 0) {
                    this.findChildList(rootNds[i][this.childrenTag], childNds);
                }
            }
            return rootNds;
        },
        findRootList: function (arr) {
            var rootNds = [], otherNds = [];
            for (var i = 0; i < arr.length; i++) {
                var flag = true;
                for (var j = 0; i !== j && j < arr.length; j++) {
                    if (arr[i][this.keyMap.parentId] === arr[j][this.keyMap.id]) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    rootNds.push(arr[i]);
                } else {
                    otherNds.push(arr[i]);
                }
            }
            return {rootNds: rootNds, otherNds: otherNds};
        }
    };
複製代碼

這裏提供了兩個可用的方法,toSingle和toList。toSingle是將樹狀對象轉換爲平面對象,toList反之。爲了可擴展性,不要去將關聯字段硬編碼化,採用配置的方法:childrenTag字段和keyMap對象用來管理數據之間的關聯關係。數組

接下來咱們來驗證一下效果:bash

var list1 = [
        {
            "id": 1,
            "name": "新建文件夾1",
            "type": 1,
            "parentId": 0,
            "children": [{"id": 3, "name": "新建文件夾3", "type": 1, "parentId": 1, "children": []}, {
                "id": 4,
                "name": "新建文件夾4",
                "type": 2,
                "parentId": 1,
                "children": [{"id": 8, "name": "新建文件夾8", "type": 2, "parentId": 4, "children": []}, {
                    "id": 9,
                    "name": "新建文件夾9",
                    "type": 2,
                    "parentId": 4,
                    "children": []
                }]
            }]
        }, {
            "id": 2,
            "name": "新建文件夾2",
            "type": 1,
            "parentId": 0,
            "children": [{
                "id": 5,
                "name": "新建文件夾5",
                "type": 2,
                "parentId": 2,
                "children": [{"id": 10, "name": "新建文件夾10", "type": 2, "parentId": 5}]
            }, {"id": 6, "name": "新建文件夾6", "type": 2, "parentId": 2, "children": []}, {
                "id": 7,
                "name": "新建文件夾7",
                "type": 2,
                "parentId": 2,
                "children": []
            }]
        }
    ];
    console.log(treeUtil.toSingle(list1));
複製代碼

result: 服務器

abc.png

接下來再驗證一下toList:數據結構

var list2 = [
        {"id": 1, "name": "新建文件夾1", "type": 1, "parentId": 0},
        {"id": 3, "name": "新建文件夾3", "type": 1, "parentId": 1},
        {"id": 4, "name": "新建文件夾4", "type": 2, "parentId": 1},
        {"id": 8, "name": "新建文件夾8", "type": 2, "parentId": 4},
        {"id": 9, "name": "新建文件夾9", "type": 2, "parentId": 4},
        {"id": 2, "name": "新建文件夾2", "type": 1, "parentId": 0},
        {"id": 5, "name": "新建文件夾5", "type": 2, "parentId": 2},
        {"id": 10, "name": "新建文件夾10", "type": 2, "parentId": 5},
        {"id": 6, "name": "新建文件夾6", "type": 2, "parentId": 2},
        {"id": 7, "name": "新建文件夾7", "type": 2, "parentId": 2}
    ];
    console.log(treeUtil.toList(list2));
複製代碼

result: ui

def.png

本次分享就到這裏。若有問題,請聯繫做者。 若是這篇文章對你有幫助,請點擊喜歡來收藏此文章。this

相關文章
相關標籤/搜索