基础数据
const arr = [
{ id: 1, name: '分类1', pid: 0 },
{ id: 2, name: '分类2', pid: 1 },
{ id: 3, name: '分类3', pid: 1 },
{ id: 4, name: '分类4', pid: 3 },
{ id: 5, name: '分类5', pid: 4 },
];
转化后的数据
[
{
id: 1,
name: '分类1',
pid: 0,
children: [
{
id: 2,
name: '分类2',
pid: 1,
children: [],
},
{
id: 3,
name: '分类3',
pid: 1,
children: [],
},
{
id: 4,
name: '分类4',
pid: 1,
children: [],
},
],
},
];
1.递归(优点:逻辑简单好实现;缺点:性能不高,数据量大时耗时较多)
// 递归生成 children
const getChild = (data, result, pid) => {
for (const item of data) {
if (item.pid === pid) {
const newItem = { ...item, children: [] };
result.push(newItem);
getChild(data, newItem.children, item.id);
}
}
};
const buildTreeOne = (data, pid) => {
const result = [];
getChild(data, result, pid);
return result;
};
2.采用map结构进行存储数据
const buildTreeTwo = (data) => {
const result = [];
const itemMap = {};
for (const item of data) {
itemMap[item.id] = { ...item, children: [] };
}
for (const i of data) {
const id = i.id;
const pid = i.pid;
const treeItem = itemMap[id];
// pid为0 则为根节点数据
if (i.pid === 0) {
result.push(treeItem);
} else {
// 下级节点是否存在该叶子节点,无,则创建为叶子节点
if (!itemMap[pid]) {
itemMap[pid] = {
children: [],
};
}
// 其余情况均放置在子节点的节点中
itemMap[pid].children.push(treeItem);
}
}
return result;
};
3.针对第2种方法的性能优化,直接从Map找对应的数据做存储。不同点在遍历的时候即做Map存储
const buildTreeThree = (data) => {
const result = [];
const itemMap = {};
for (const i of data) {
const id = i.id;
const pid = i.pid;
if (!itemMap[id]) {
itemMap[id] = {
children: [],
};
}
itemMap[id] = {
...i,
children: [],
};
const treeItem = itemMap[id];
if (i.pid === 0) {
result.push(treeItem);
} else {
if (!itemMap[pid]) {
itemMap[pid] = {
children: [],
};
}
itemMap[pid].children.push(treeItem);
}
}
return result;
}