跳至主要內容

TreeUtil - 树工具

会功夫的李白...大约 3 分钟通用树工具

在处理数据时,尤其是表格类、树组件数据,后端返回的数据可能不是一个属性结构的数据,或者其他树结构处理,这个时候我们需要对数据进行递归、拼接等一系列操作,于是 TreeUtil 应运而生,提供构建、处理树形数据的方法,让树形数据的处理更加简洁高效!

1. 常规使用

如有以下数组:

const list = [
    {
        "deptId": 100,
        "parentId": 0,
        "deptName": "百涂科技",
        "children": []
    },
    {
        "deptId": 101,
        "parentId": 100,
        "deptName": "深圳总公司",
        "children": []
    },
    {
        "deptId": 102,
        "parentId": 100,
        "deptName": "长沙分公司",
        "children": []
    },
    {
        "deptId": 103,
        "parentId": 101,
        "deptName": "研发部门",
        "children": []
    },
    {
        "deptId": 104,
        "parentId": 101,
        "deptName": "市场部门",
        "children": []
    },
    {
        "deptId": 105,
        "parentId": 101,
        "deptName": "测试部门",
        "children": []
    },
    {
        "deptId": 106,
        "parentId": 101,
        "deptName": "财务部门",
        "children": []
    },
    {
        "deptId": 107,
        "parentId": 101,
        "deptName": "运维部门",
        "children": []
    },
    {
        "deptId": 108,
        "parentId": 102,
        "deptName": "市场部门",
        "children": []
    },
    {
        "deptId": 109,
        "parentId": 102,
        "deptName": "财务部门",
        "children": []
    }
]

通过树形构建函数 buildTree 来构建树形结构数据:

TreeUtil.buildTree(list, 'deptId', 'parentId', 'children');

构建树形结构时,默认会添加 __built_tag__tree_level 参数,用于分别表示是否已参与构建树和当前元素层级(从1开始),buildTree 构建后的数据会保留原数组长度,如果你只想得到一个树,那么你可以使用 buildCommonTree 函数

最终结果:

[
    {
        "deptId": 100,
        "parentId": 0,
        "deptName": "百涂科技",
        "children": [
            {
                "deptId": 101,
                "parentId": 100,
                "deptName": "深圳总公司",
                "children": [
                    {
                        "deptId": 103,
                        "parentId": 101,
                        "deptName": "研发部门",
                        "children": [],
                        "__built_tag": true,
                        "__tree_level": 3
                    },
                    {
                        "deptId": 104,
                        "parentId": 101,
                        "deptName": "市场部门",
                        "children": [],
                        "__built_tag": true,
                        "__tree_level": 3
                    },
                    {
                        "deptId": 105,
                        "parentId": 101,
                        "deptName": "测试部门",
                        "children": [],
                        "__built_tag": true,
                        "__tree_level": 3
                    },
                    {
                        "deptId": 106,
                        "parentId": 101,
                        "deptName": "财务部门",
                        "children": [],
                        "__built_tag": true,
                        "__tree_level": 3
                    },
                    {
                        "deptId": 107,
                        "parentId": 101,
                        "deptName": "运维部门",
                        "children": [],
                        "__built_tag": true,
                        "__tree_level": 3
                    }
                ],
                "__built_tag": true,
                "__tree_level": 2
            },
            {
                "deptId": 102,
                "parentId": 100,
                "deptName": "长沙分公司",
                "children": [
                    {
                        "deptId": 108,
                        "parentId": 102,
                        "deptName": "市场部门",
                        "children": [],
                        "__built_tag": true,
                        "__tree_level": 3
                    },
                    {
                        "deptId": 109,
                        "parentId": 102,
                        "deptName": "财务部门",
                        "children": [],
                        "__built_tag": true,
                        "__tree_level": 3
                    }
                ],
                "__built_tag": true,
                "__tree_level": 2
            }
        ],
        "__tree_level": 1
    },
    {
        "deptId": 101,
        "parentId": 100,
        "deptName": "深圳总公司",
        "children": [
            {
                "deptId": 103,
                "parentId": 101,
                "deptName": "研发部门",
                "children": [],
                "__built_tag": true,
                "__tree_level": 3
            },
            {
                "deptId": 104,
                "parentId": 101,
                "deptName": "市场部门",
                "children": [],
                "__built_tag": true,
                "__tree_level": 3
            },
            {
                "deptId": 105,
                "parentId": 101,
                "deptName": "测试部门",
                "children": [],
                "__built_tag": true,
                "__tree_level": 3
            },
            {
                "deptId": 106,
                "parentId": 101,
                "deptName": "财务部门",
                "children": [],
                "__built_tag": true,
                "__tree_level": 3
            },
            {
                "deptId": 107,
                "parentId": 101,
                "deptName": "运维部门",
                "children": [],
                "__built_tag": true,
                "__tree_level": 3
            }
        ],
        "__built_tag": true,
        "__tree_level": 2
    },
    {
        "deptId": 102,
        "parentId": 100,
        "deptName": "长沙分公司",
        "children": [
            {
                "deptId": 108,
                "parentId": 102,
                "deptName": "市场部门",
                "children": [],
                "__built_tag": true,
                "__tree_level": 3
            },
            {
                "deptId": 109,
                "parentId": 102,
                "deptName": "财务部门",
                "children": [],
                "__built_tag": true,
                "__tree_level": 3
            }
        ],
        "__built_tag": true,
        "__tree_level": 2
    },
    {
        "deptId": 103,
        "parentId": 101,
        "deptName": "研发部门",
        "children": [],
        "__built_tag": true,
        "__tree_level": 3
    },
    {
        "deptId": 104,
        "parentId": 101,
        "deptName": "市场部门",
        "children": [],
        "__built_tag": true,
        "__tree_level": 3
    },
    {
        "deptId": 105,
        "parentId": 101,
        "deptName": "测试部门",
        "children": [],
        "__built_tag": true,
        "__tree_level": 3
    },
    {
        "deptId": 106,
        "parentId": 101,
        "deptName": "财务部门",
        "children": [],
        "__built_tag": true,
        "__tree_level": 3
    },
    {
        "deptId": 107,
        "parentId": 101,
        "deptName": "运维部门",
        "children": [],
        "__built_tag": true,
        "__tree_level": 3
    },
    {
        "deptId": 108,
        "parentId": 102,
        "deptName": "市场部门",
        "children": [],
        "__built_tag": true,
        "__tree_level": 3
    },
    {
        "deptId": 109,
        "parentId": 102,
        "deptName": "财务部门",
        "children": [],
        "__built_tag": true,
        "__tree_level": 3
    }
]

2. 自定义处理

如果你想自己处理树元素,可以通过 buildTreeMapper 函数实现

TreeUtil.buildTreeMapper(list2, 'deptId', 'parentId', (current, parent, parentChilds, level) => {
    if (level !== 1) {
        // 根节点遍历时没有父级
        parent['children'] = parentChilds;
    }
    current['level'] = level;
    return current;
});

3. 参数

构建树结构 - buildTree 和 buildCommonTree

序号名称类型含义
1list数组要构建树结构数据的数组
2idName字符串主键属性名
3parentName字符串父级主键属性名
4childName字符串子节点属性名
5levelName字符串级别属性名
6mapper函数节点处理函数
7leafMapper函数叶子节点处理函数

mapper 函数

序号名称类型含义
1current任意当前元素
2parent任意父级元素
3parentChildList数组父级子元素集合
4level数字当前层级

leafMapper 函数

序号名称类型含义
1current任意当前元素

递归树结构变换器 - buildTreeMapper

序号名称类型含义
1list数组要构建树结构数据的数组
2idName字符串主键属性名
3parentName字符串父级主键属性名
4mapper函数节点处理函数
5leafMapper函数叶子节点处理函数