列表转树形结构
直接上代码
// ! 列表转树形结构
export function listToTree (list, rootId) {
const arr = []
list.forEach(item => {
// 根节点
if (item.pid === rootId) {
// 寻亲
const children = listToTree(list, item.id)
// 如果没有儿子,儿子返回的arr就为空,就不添加children
if (children.length) {
item.children = children
}
arr.push(item)
}
// ! 结束条件实际是else 也就是最后的子id被当作父id时,list列表中没有对应的pid与之对应
// 例如:当list:[a:{id:1,pid:''},b:{id:2,pid:1},c:{id:3,pid:2}]
// 当以最后一个儿子的id:3 去调用listToTree,则 rootId 为3 ,而list数组中没有item的pid与之对应,则递归结束
})
return arr
}
树形结构转列表(扁平化)
方式一
// arr用来保存结果
function treeToList (tree, arr) {
tree.forEach(item => {
// 如果有孩子
if (Array.isArray(item.children)) {
treeToList(item.children, arr)
// 去除children 用来浅拷贝 拷贝除了children以外的属性
const obj = {}
Object.keys(item).forEach(key => {
if (key !== 'children') {
obj[key] = item[key]
}
})
arr.push(obj)
} else {
// 没有孩子
arr.push(item)
}
})
}
const a = [{id: 1, pid: '',children: [{ id: 2, pid: 1, children: [{ id: 3, pid: 2 }]}]}]
const arr = []
treeToList(a,arr)
console.log(arr)
方式二
function treeToList (tree) {
let arr = []
tree.forEach(item => {
// 如果有孩子
if (Array.isArray(item.children)) {
arr = arr.concat(treeToList(item.children))
// #1 去除children 用来浅拷贝 拷贝除了children以外的属性
/* const obj = {}
Object.keys(item).forEach(key => {
if (key !== 'children') {
obj[key] = item[key]
}
})
arr = arr.concat(obj) */
// #2 直接删除属性
delete item.children
arr = arr.concat(item)
} else {
// 没有孩子
arr = arr.concat(item)
}
})
return arr
}
const a = [{id: 1, pid: '',children: [{ id: 2, pid: 1, children: [{ id: 3, pid: 2 }]}]}]
const arr = treeToList(a)
console.log(arr)
方式三:这种还需要后期将children去掉
// 递归 + reduce
function flat (datas) {
return datas.reduce((acc, cur, curIndex) => {
return acc.concat(
cur,
Array.isArray(cur.children) ? flat(cur.children) : []
)
}, [])
}
// 去除children
const a = [{id: 1, pid: '',children: [{ id: 2, pid: 1, children: [{ id: 3, pid: 2 }]}]}]
const a2 = flat(a)
a2.forEach(item => {
delete item.children
})
console.log(a2)