实现
const arr2Tree =
fn =>
(arr, idKey = 'id', childKey = 'children', treeRoot = -1) => {
if (!Array.isArray(arr)) {
return arr;
}
const tmpData = {};
const keys = arr.map(v => v[idKey]);
[...arr].map(v => {
const item = {...v};
const {[idKey]: id} = item;
if (id != null) {
let {parentId} = item;
if (parentId == null) {
parentId = fn?.(item) ?? treeRoot;
item.parentId = parentId;
}
if (!tmpData[id]) {
tmpData[id] = [];
}
item[childKey] = tmpData[id];
if (!tmpData[parentId]) {
tmpData[parentId] = [];
}
if (!tmpData[treeRoot]) {
tmpData[treeRoot] = [];
}
const hasParent = keys.includes(parentId);
if (hasParent) {
tmpData[parentId].push(item);
} else {
tmpData[treeRoot].push(item);
}
}
});
return tmpData[treeRoot];
};
- fn:回调函数
- arr:数组
- idKey:节点 ID key
- childKey:子节点 key
- treeRoot:根节点
这是一个高阶函数,传入的 fn 函数可以自定义处理当前节点 parentId 。
例如:由此高阶函数可以定义一个通过 path 地址自动将路由数组转为路由树结构的函数。
const arr2TreeByPath = (data, idKey = 'path', childKey = 'children', treeRoot = null) =>
arr2Tree(item => {
const id = item[idKey];
const hasSub = id.match(/.*\/[^:/]+\/:[^/]+/);
if (hasSub) {
return hasSub[0].match(/(.*)\/:+/)?.[1] ?? treeRoot;
} else {
return id.match(/(.*)\/+/)?.[1] ?? treeRoot;
}
})(data, idKey, childKey, treeRoot);
示例
const arr = [
{
parentId: '-1',
id: '0',
name: '0',
},
{
parentId: '0',
id: '01',
name: '01',
},
{
parentId: '-1',
id: '2',
name: '2',
},
{
parentId:'0',
id: '03',
name: '03',
},
{
parentId: '1',
id: '11',
name: '11',
},
{
parentId: '2',
id: '21',
name: '21',
},
{
parentId: '-1',
id: '1',
name: '1',
},
{
parentId: '2',
id: '22',
name: '22',
},
{
parentId: '0',
id: '02',
name: '02',
},
{
parentId: '1',
id: '12',
name: '12',
},
{
parentId: '21',
id: '211',
name: '211',
},
];
const arr1 = [
{
path: '/a',
name: 'a',
},
{
path: '/a/1',
name: 'a1',
},
{
path: '/c',
name: 'c',
},
{
path: '/a/3',
name: 'a3',
},
{
path: '/b/1',
name: 'b1',
},
{
path: '/c/1',
name: 'c1',
},
{
path: '/b',
name: 'b',
},
{
path: '/c/2',
name: 'c2',
},
{
path: '/a/2',
name: 'a2',
},
{
path: '/b/2',
name: 'b2',
},
{
path: '/b/1/1',
name: 'b11',
},
];
arr2Tree()(arr);
arr2TreeByPath(arr1);