数据
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: 3},
]
let tree = [
{
"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": []
}
]
}
]
}
]
tree扁平化
- 递归实现
遍历tree,每一项加进结果集,如果有children且长度不为0,则递归遍历。
function treeToArray(tree) {
let res = []
for (const item of tree) {
const { children, ...i } = item
if (children && children.length) {
res = res.concat(treeToArray(children))
}
res.push(i)
}
return res
}
- reduce实现
function treeToArray(tree) {
return tree.reduce((res, item) => {
const { children, ...i } = item
return res.concat(i, children && children.length ? treeToArray(children) : [])
}, [])
}
扁平化数组转tree
- 递归实现
最常用到的就是递归实现,思路也比较简单,实现一个方法,该方法传入tree父节点和父id,循环遍历数组,无脑查询,找到对应的子节点,push到父节点中,再递归查找子节点的子节点。
function arrayToTree(items) {
let res = []
let getChildren = (res, pid) => {
for (const i of items) {
if (i.pid === pid) {
const newItem = { ...i, children: [] }
res.push(newItem)
getChildren(newItem.children, newItem.id)
}
}
}
getChildren(res, 0)
return res
}
- map对象实现
先转map再找对应关系
function arrayToTree(items) {
let res = [] // 存放结果集
let map = {}
// 先转成map存储
for (const i of items) {
map[i.id] = { ...i, children: [] }
}
for (const i of items) {
const newItem = map[i.id]
if (i.pid === 0) {
res.push(newItem)
} else {
if (Object.prototype.hasOwnProperty.call(map, i.pid)) {
map[i.pid].children.push(newItem)
}
}
}
return res
}
注意: Object.prototype.hasOwnProperty: 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性,会忽略掉那些从原型链上继承到的属性。
function arrayToTree(items) {
let res = [] // 存放结果集
let map = {}
// 判断对象是否有某个属性
let getHasOwnProperty = (obj, property) => Object.prototype.hasOwnProperty.call(obj, property)
// 边做map存储,边找对应关系
for (const i of items) {
map[i.id] = {
...i,
children: getHasOwnProperty(map, i.id) ? map[i.id].children : []
}
const newItem = map[i.id]
if (i.pid === 0) {
res.push(newItem)
} else {
if (!getHasOwnProperty(map, i.pid)) {
map[i.pid] = {
children: []
}
}
map[i.pid].children.push(newItem)
}
}
return res
}