1. 程式人生 > 實用技巧 >javascript將平行的擁有上下級關係的資料轉換成樹形結構

javascript將平行的擁有上下級關係的資料轉換成樹形結構

轉換函式

var Littlehow = {};
/**
 * littlehow 2019-05-15
 * 平行資料樹形轉換器
 * @type {{format: tree.format, sort: tree.sort, map: (function(*, *): {root, da})}}
 */
Littlehow.tree = {
    /**
     *  將平行結果轉換成樹形結構,父編號不可為空,如果為最高,則可以設定root等字樣
     *  如果有排序欄位,將排序完成後返回
     *  如:data:[{id:'1', parentId:'root', name:'test'}, {id:'2', parentId:'1', name:'test1'},{id:'3', parentId:'1', name:'test2'}]
     *     format:{id:'id', root:'root', 'pid':'parentId', child:'children'}
     *  解析後的資料形式為:
     *  [{id:'1','parentId':'root',name:'test', children:[{id:'2',parentId:'1',name:'test1'},{id:'3',parentId:'1',name:'test2'}]}]
     *  @param data   -- 需要轉換的資料
     *  @param format -- 轉換格式 {id:'', root:'', pid:'', child:'', sort:{field:'', direct:1}}
     *  @return {*} 轉換後的資料
     */
    format : function(data, format) {
        //如果data,沒有資料,則將data原樣返回
        if (!data || data.length <= 0) return data;
        var map = this.map(data, format);
        //再遍歷原資料進行樹形填充
        for (var i = 0, len = data.length; i < len; i++) {
            var d = data[i];
            if (map.dm[d[format.pid]]) {
                map.dm[d[format.pid]][format.child].push(d);
            }
        }
        //最後將root排序後返回
        this.sort(map.root, format);
        return map.root;
    },
    /**
     * 平行資料對映為map
     * @param data     -- 平行資料
     * @param format   -- tree格式化資訊
     * @return {{d, root}}  -- 返回資料和根資料map
     */
    map : function(data, format) {
        var dataMap = {};//全資料對映
        var root = [];//根
        for (var i = 0, len = data.length; i < len; i++) {
            var d = data[i];
            //初始化child欄位,如果不想要這裡初始化也可以在樹形填充出進行判斷初始化
            d[format.child] = [];
            dataMap[d[format.id]] = d;
            if (data[i][format.pid] === format.root) {//將root記錄到root陣列
                root.push(d);
            }
        }
        return {dm : dataMap, root : root};
    },
    /**
     * 進行排序  format.sort格式為sort:{field:'', direct:1},其中direct=1為正序,direct=-1為逆序
     * @param result  -- 結果集
     * @param format  -- 格式化
     */
    sort : function(result, format) {
        if (!format.sort) return;//沒有排序配置則不進行排序
        result.sort(function(a, b) {
            var as = a[format.sort.field];
            var bs = b[format.sort.field];
            return (as - bs) * format.sort.direct;
        });
        //如果result中有child,則繼續進行排序
        for (var i = 0, len = result.length; i < len; i++) {
            if (result[i][format.child].length > 0) {
                this.sort(result[i][format.child], format);
            }
        }
    }
};

  

呼叫示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>tree case</title>
    <script src="TreeUtils.js" type="application/javascript"></script>
    <script type="application/javascript">
        var data = [
            {
                "menuName": "系統管理",
                "parentId": "root",
                "iconCls": "el-icon-s-tools",
                "request": null,
                "leaf": "0",
                "sortNo": 30,
                "menuId": "1"
            },
            {
                "menuName": "人員管理",
                "parentId": "1",
                "iconCls": null,
                "request": "/system/user",
                "leaf": "1",
                "sortNo": 3,
                "menuId": "2"
            },
            {
                "menuName": "角色管理",
                "parentId": "1",
                "iconCls": null,
                "request": "/system/role",
                "leaf": "1",
                "sortNo": 6,
                "menuId": "3"
            },
            {
                "menuName": "選單管理",
                "parentId": "1",
                "iconCls": null,
                "request": "/system/menu",
                "leaf": "1",
                "sortNo": 9,
                "menuId": "4"
            },
            {
                "menuName": "系統配置",
                "parentId": "1",
                "iconCls": null,
                "request": "/system/config",
                "leaf": "1",
                "sortNo": 12,
                "menuId": "5"
            },
            {
                "menuName": "字典管理",
                "parentId": "1",
                "iconCls": null,
                "request": "/system/dictionary",
                "leaf": "1",
                "sortNo": 15,
                "menuId": "6"
            },
            {
                "menuName": "內容管理",
                "parentId": "root",
                "iconCls": "el-icon-tickets",
                "request": null,
                "leaf": "0",
                "sortNo": 18,
                "menuId": "21"
            },
            {
                "menuName": "banner",
                "parentId": "21",
                "iconCls": null,
                "request": "/content/banner",
                "leaf": "1",
                "sortNo": 3,
                "menuId": "22"
            },
            {
                "menuName": "公告列表",
                "parentId": "21",
                "iconCls": null,
                "request": "/content/attention",
                "leaf": "1",
                "sortNo": 9,
                "menuId": "23"
            },
            {
                "menuName": "App版本管理",
                "parentId": "root",
                "iconCls": "el-icon-tickets",
                "request": null,
                "leaf": "0",
                "sortNo": 27,
                "menuId": "91"
            },
            {
                "menuName": "App版本管理",
                "parentId": "91",
                "iconCls": null,
                "request": "/app/manager",
                "leaf": "1",
                "sortNo": 3,
                "menuId": "92"
            }
        ];

        var format = {
            id:'menuId', //選單編號,作為樹形查詢id
            root:'root', //頂層節點的parentId是root
            pid:'parentId',//父節點標識欄位為parentId
            child:'children',//構造出的樹形子節點陣列名為children
            sort:{field:'sortNo', direct:1}};//排序欄位為sortNo,且正序

        var result = Littlehow.tree.format(data, format);
        console.log(result);
        document.write(JSON.stringify(result));
    </script>
</head>
<body>

</body>
</html>

  

輸出結果如下

[{
	"menuName": "內容管理",
	"parentId": "root",
	"iconCls": "el-icon-tickets",
	"request": null,
	"leaf": "0",
	"sortNo": 18,
	"menuId": "21",
	"children": [{
		"menuName": "banner",
		"parentId": "21",
		"iconCls": null,
		"request": "/content/banner",
		"leaf": "1",
		"sortNo": 3,
		"menuId": "22",
		"children": []
	}, {
		"menuName": "公告列表",
		"parentId": "21",
		"iconCls": null,
		"request": "/content/attention",
		"leaf": "1",
		"sortNo": 9,
		"menuId": "23",
		"children": []
	}]
}, {
	"menuName": "App版本管理",
	"parentId": "root",
	"iconCls": "el-icon-tickets",
	"request": null,
	"leaf": "0",
	"sortNo": 27,
	"menuId": "91",
	"children": [{
		"menuName": "App版本管理",
		"parentId": "91",
		"iconCls": null,
		"request": "/app/manager",
		"leaf": "1",
		"sortNo": 3,
		"menuId": "92",
		"children": []
	}]
}, {
	"menuName": "系統管理",
	"parentId": "root",
	"iconCls": "el-icon-s-tools",
	"request": null,
	"leaf": "0",
	"sortNo": 30,
	"menuId": "1",
	"children": [{
		"menuName": "人員管理",
		"parentId": "1",
		"iconCls": null,
		"request": "/system/user",
		"leaf": "1",
		"sortNo": 3,
		"menuId": "2",
		"children": []
	}, {
		"menuName": "角色管理",
		"parentId": "1",
		"iconCls": null,
		"request": "/system/role",
		"leaf": "1",
		"sortNo": 6,
		"menuId": "3",
		"children": []
	}, {
		"menuName": "選單管理",
		"parentId": "1",
		"iconCls": null,
		"request": "/system/menu",
		"leaf": "1",
		"sortNo": 9,
		"menuId": "4",
		"children": []
	}, {
		"menuName": "系統配置",
		"parentId": "1",
		"iconCls": null,
		"request": "/system/config",
		"leaf": "1",
		"sortNo": 12,
		"menuId": "5",
		"children": []
	}, {
		"menuName": "字典管理",
		"parentId": "1",
		"iconCls": null,
		"request": "/system/dictionary",
		"leaf": "1",
		"sortNo": 15,
		"menuId": "6",
		"children": []
	}]
}]