假如有个需求,是如下结构:
let 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},
]
通过pid这个字段,要转成树结构,就是这样:
[
{
"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": 3,
"children": [
{
"id": 5,
"name": "部门5",
"pid": 4,
"children": []
}
]
}
]
}
]
}
]
思路如下:
先把数据转成Map形式去存储,再去遍历这个Map找到对应的数据,完整代码:
let 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},
]
let result = []
let trees = {}
// 遍历给每一个对象添加一个children属性并转换成Map形式;并添加进trees对象,id为键
arr.forEach(item => {
item.children = []
trees[item.id] = item
})
// 遍历查找对应的Map做存储
arr.forEach(item => {
// 找到pid不为0的对象
if(trees[item.pid]){
// 因为pid对应的父节点是id,所以通过pid找到父节点再把当前的对象添加进入子数组里面
trees[item.pid].children.push(item)
}
// 把pid为0的对象添加进最终的数组result,做为父节点
if(item.pid == 0){
// item是引用类型(浅拷贝),针对当前数据所以只需push一次到result
result.push(item)
}
})
但是目前这个有个缺点,就是假如有两个父节点,就会有问题,因为这里是用的pid===0来判断的,更完整的如下:
// 假设有如下数据,需要转成树结构:
let arr = [
{ id: 1, parentId: null, name: 'a' },
{ id: 2, parentId: null, name: 'b' },
{ id: 3, parentId: 1, name: 'c' },
{ id: 4, parentId: 2, name: 'd' },
{ id: 5, parentId: 1, name: 'e' },
{ id: 6, parentId: 3, name: 'f' },
{ id: 7, parentId: 4, name: 'g' },
{ id: 8, parentId: 7, name: 'h' },
]
// 定义最终输出的数组
let trees = []
// 定义一个map
let map = new Map()
// 遍历源数组,给map添加数据,这里的map是浅拷贝,后续修改map会直接修改到arr数组
for (let v of arr){
// set(key,value)方法: 向当前Map对象中添加一个值,返回的Map对象,所以支持链式写法
map.set(v.id, v)
}
for (let v of arr){
const pId = v.parentId
// 方法has(key) 返回一个bool值,用来表明map 中是否存在指定元素.
// 如果map中不存在当前元素parentId,则该元素为根元素,当前数据针对null,是不存在的
if (!map.has(pId)) {
// push的对象是引用类型(浅拷贝)
trees.push(v)
}
// 如果map中存在 当前元素的parentId,则该元素不为根元素
else {
// get(key) 通过key找到value,如果找不到,返回undefined
// 得到的 parent 是引用类型
const parent = map.get(pId)
// instanceof方法:用于判断一个变量是否某个对象的实例
// 这里的意思是:如果parent没有children这个字段或者不是一个数组,则手动添加一个children属性为空数组
!(parent.children instanceof Array) && (parent.children = [])
parent.children.push(v)
}
}
console.log(trees)