在前端开发过程中,使用到树结构的概率还是很高的,后端开发往往是直接返回一个扁平的数组给你,我们需要自己处理成想要的结构。
将一个大的数组转为一个树结构的可用数据。
一、需求分析
1、后端返回的数据
let dataList = [
{
name: 'f0',
id: '1',
pid: '0',
},
{
name: 'f01',
id: '2',
pid: '1',
},
{
name: 'f02',
id: '3',
pid: '1',
},
{
name: 'f021',
id: '6',
pid: '3',
},
{
name: 'f021',
id: '7',
pid: '6',
},
{
name: 'f40',
id: '4',
pid: '0',
},
{
name: 'f41',
id: '5',
pid: '4',
}
];
2、需要处理后的数据
let dataList = [{
name: 'f0',
id: '1',
pid: '0',
children: [{
name: 'f01',
id: '2',
pid: '1',
},
{
name: 'f02',
id: '3',
pid: '1',
children: [{
name: 'f021',
id: '6',
pid: '3',
children: [{
name: 'f021',
id: '7',
pid: '6',
}]
}]
}
]
},
{
name: 'f40',
id: '4',
pid: '0',
children: [{
name: 'f41',
id: '5',
pid: '4',
}]
}
];
3、下面介绍几种常用的方法帮助前端的小伙伴将一个大的数组生成树的结构
二、方式一:使用递归的方式
这种方法比较复杂,此处就不写了
三、方式二:使用forEach循环的方式
1、实现的代码
let rootMenus = [];
let map = {};
dataList.sort((a, b) => a.pid - b.pid);
dataList.forEach(resource => {
resource.children = [];
map[resource.id] = resource;
if (resource.pid == 0) {
rootMenus.push(resource);
} else {
if (map[resource.pid]) {
map[resource.pid].children.push(resource)
} else {
throw new Error(`当前循环的数据pid=${resource.pid}有错误`);
}
}
})
console.log(rootMenus);
2、理解上面的代码
很多人不能理解的地方可能就是map[resource.pid].children.push(resource)这行代码了,
其实简单的理解是map[resource.pid]==上面的resource
3、上面的代码不如之处
pid必须是0,不然就会抛出异常,局限性比较大
四、方式三:使用reduce函数(推荐使用的方式)
1、代码的实现
// 第一次是将全部的permissionId作为对象的key重组成一个对象
let formatObj = dataList.reduce((pre, cur) => {
return {...pre, [cur['id']]: cur}
}, {});
console.log(formatObj);
let formatArray = dataList.reduce((arr, cur) => {
let pid = cur.pid ? cur.pid : 0;
let parent = formatObj[pid];
if (parent) {
parent.children ? parent.children.push(cur) : parent.children=[cur];
} else {
arr.push(cur)
}
return arr;
}, []);
console.log(formatArray);
评论区