在前端开发中,有个很常见的需求是需要生成一些树形结构的场景,往往是后端返回一个包含所有节点数组(好的后端会帮你生成树形结构),那么当后端不给我们生成怎没办呢?那咱们就得自食其力了。
下面给大家带来几种方法处理这种树形问题。
举个例子给大家演示一下:
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: 0 },
{ id: 6, name: "部门6", pid: 5 },
];
/**
* 生成树形结构方法一
* 采用递归的方法实现
* @param {Array} data 数据源
* @param {Number} rootId 根节点id
*/
function generateTree1(data, rootId) {
function getChildren(data, result = [], id) {
for (let i = 0; i < data.length; i++) {
if (data[i].pid === id) {
data[i].children || (data[i].children = []);
result.push(data[i]);
getChildren(
data.filter((it) => it.id !== data[i].id),
data[i].children,
data[i].id
);
}
}
}
const result = [];
getChildren(data, result, rootId);
return result;
}
// console.log(generateTree1(arr, 0));
/**
* 生成树形结构方法二
* 采用数组自带的方法实现
*/
function generateTree2(data, rootId) {
return data
.filter((item) => item.pid === rootId)
.map((item) => ({ ...item, children: generateTree2(data, item.id) }));
}
// console.log(generateTree2(arr, 0));
/**
* 生成树形结构方法三
* 采用reduce方法实现
*/
function generateTree3(data, rootId) {
return data.reduce((result, item) => {
if (item.pid === rootId) {
item.children = generateTree3(data, item.id);
result.push(item);
}
return result;
}, []);
}
// console.log(generateTree3(arr, 0));
/**
* 生成树形结构方法四
* 不使用递归的方法实现
*/
function generateTree4(data, rootId) {
const map = new Map();
for (let i = 0; i < data.length; i++) {
map.set(data[i].id, data[i]);
}
const result = [];
for (let i = 0; i < data.length; i++) {
if (data[i].pid === rootId) {
result.push(data[i]);
} else {
const parent = map.get(data[i].pid);
if (parent) {
parent.children = parent.children || [];
parent.children.push(data[i]);
}
}
}
return result;
}
console.log(generateTree4(arr, 0));
前三种方法本质上是递归的思想,只是运用了数组的不同方法。
总结
- 递归方法:代码简洁,但在数据量较大时可能会有性能问题。
- 迭代方法:性能较好,适合处理大量数据。
- 遍历数组,将每个元素转换为树节点,并用一个对象(或Map)来存储,以id为键,方便快速查找
- 再次遍历数组,根据每个元素的parentId找到其父节点,并将当前节点添加到父节点的children数组中。
- 确定根节点,通常是parentId为null、undefined、0或者特定值(比如0)的元素,然后将这些根节点收集起来作为树的顶层