1.前言
前端在开发时候,有时候接到后端数据需要将数据转成树形结构渲染上页面,而我们一般接受到的数据都是偏平状,怎么样转成树形呢,看下图,很明显树状数据结构更有层次感
2.解决方法
2.1.映射加引用的方法,非递归
/**
* 把平铺的数组结构转成树形结构
*
* [
* {id:"01", pid:"", "name":"小明" },
* {id:"02", pid:"01", "name":"小刘" }
* ]
* 上面的结构说明: 小明是小刘的上级
*/
export function tranListToTreeData(list) {
// 1. 定义两个变量
const treeList = [], map = {}
// 2. 建立一个映射关系,通过id找元素并给每个元素补充children属性
list.forEach(item => {
if (!item.children) {
item.children = []
}
map[item.id] = item
//这行代码的意思是先在map里面存入id,然后在对应id下面加入item
})
list.forEach(item => {
// 对于每一个元素来说,先找它的上级
// 如果能找到,说明它有上级,则要把它添加到上级的children中去
// 如果找不到,说明它没有上级,直接添加到 treeList
const parent = map[item.pid]
// 如果存在上级则表示item不是最顶层的数据
if (parent) {
parent.children.push(item)
} else {
// 如果不存在上级 则是顶层数据,直接添加
treeList.push(item)
}
})
// 返回
return treeList
}
2.2.递归方法
const tranListToTreeData = (
pid = 0,
{ idName = "id", parentIdName = "pid", childName = "children" } = {}
) => {
return list.reduce((item, cur) => {
// 找到pid 的子节点之后,递归找子节点的下一级节点
if (cur[pid] === pid) {
//找上级 有的话 就存到上级的children里面去
const children = tranListToTreeData(list, cur[id]);
if (children.length) {
cur[childName] = children;
}
return [...item, cur];
}
return item;
}, []);
};
const result = tranListToTreeData(array, 0);
3.总结
其实递归和非递归的思路是差不多的就是方法不一样,给没有上级的元素建立children属性,把有上级的元素添加到上级元素的children中,这里还是推荐使用非递归方法更好懂