一、核心思想
1.数组转树
(1)循环遍历
1.定义临时对象和结果数组分别遍历存储数组中的对象和最终返回结果
2.遍历传入的数组
3.如果父在临时对象中不存在 将父加入到结果数组中
4.否则将当前对象加入到当前对象父id的children数组中
5.返回结果
(2)递归
1.定义数组存储返回结果
2.深拷贝一个数组用来循环遍历与val相等的父id
3.如果存在 则递归找到孩子并将其加入当前父id的children数组中
4.返回结果
2.树转数组
利用广度优先遍历实现树到数组,定义返回结果和队列,当队列非空时遍历队列,将当前队列的第一项出队,如果当前项有孩子则循环遍历将孩子加入队尾,循环遍历到结束,返回结果。
二、代码实现
1.数组转树
(1)循环遍历
const arr = [
{ id: "00", name: "测试", pid: "", job: "测试" },
{ id: "01", name: "张大", pid: "", job: "项目经理" },
{ id: "02", name: "小亮", pid: "01", job: "产品leader" },
{ id: "03", name: "小美", pid: "01", job: "UIleader" },
{ id: "04", name: "老马", pid: "01", job: "技术leader" },
{ id: "05", name: "老王", pid: "01", job: "测试leader" },
{ id: "06", name: "老李", pid: "01", job: "运维leader" },
{ id: "07", name: "小丽", pid: "02", job: "产品经理" },
{ id: "09", name: "小高", pid: "03", job: "UI设计师" },
{ id: "10", name: "小刘", pid: "04", job: "前端工程师" },
{ id: "13", name: "小赵", pid: "05", job: "测试工程师" },
{ id: "15", name: "小涛", pid: "06", job: "运维工程师" },
];
/**
* 循环将数组转换为树
* @param {Array} array 传入数组
* @return {Array} result 返回数组
*/
function arrayToTree(array){
//定义临时对象和结果数组分别遍历存储数组中的对象和最终返回结果
let tempObj = {},result = []
//遍历传入的数组
result = array.reduce((prev,cur)=>{
cur.children = []
tempObj[cur.id] = cur //浅拷贝
if (!tempObj[cur.pid]) {
//如果父在临时对象中不存在 将父加入到结果数组中
prev.push(cur)
} else {
//否则将当前对象加入到当前对象父id的children数组中
tempObj[cur.pid].children.push(cur)
}
return prev
},[])
//返回结果
return result
}
console.log(arrayToTree(arr))
(2)递归
const arr = [
{ id: "00", name: "测试", pid: "", job: "测试" },
{ id: "01", name: "张大", pid: "", job: "项目经理" },
{ id: "02", name: "小亮", pid: "01", job: "产品leader" },
{ id: "03", name: "小美", pid: "01", job: "UIleader" },
{ id: "04", name: "老马", pid: "01", job: "技术leader" },
{ id: "05", name: "老王", pid: "01", job: "测试leader" },
{ id: "06", name: "老李", pid: "01", job: "运维leader" },
{ id: "07", name: "小丽", pid: "02", job: "产品经理" },
{ id: "09", name: "小高", pid: "03", job: "UI设计师" },
{ id: "10", name: "小刘", pid: "04", job: "前端工程师" },
{ id: "13", name: "小赵", pid: "05", job: "测试工程师" },
{ id: "15", name: "小涛", pid: "06", job: "运维工程师" },
];
function arrayToTreeByRecursion(array, val) {
//定义数组存储返回结果
let result = [];
//深拷贝一个数组用来循环遍历与val相等的父id
let arr = JSON.parse(JSON.stringify(array));
arr.forEach((item) => {
//如果存在 则递归找到孩子并将其加入当前父id的children数组中
if (item.pid == val) {
let children = arrayToTreeByRecursion(arr, item.id);
children.length ? (item.children = children) : (item.children = []);
result.push(item);
}
});
//返回结果
return result;
}
let newTree = arrayToTreeByRecursion(arr, "")
console.log("newTree",newTree)
2.树转数组
let tree = [
{
id: "00",
job: "测试",
name: "测试",
pid: "",
children: [],
},
{
id: "01",
job: "项目经理",
name: "张大",
pid: "",
children: [
{
id: "02",
name: "小亮",
pid: "01",
job: "产品leader",
children: [
{ id: "07", name: "小丽", pid: "02", job: "产品经理", children: [] },
],
},
{
id: "03",
name: "小美",
pid: "01",
job: "UIleader",
children: [
{ id: "09", name: "小高", pid: "03", job: "UI设计师", children: [] },
],
},
{
id: "04",
name: "老马",
pid: "01",
job: "技术leader",
children: [
{
id: "10",
name: "小刘",
pid: "04",
job: "前端工程师",
children: [],
},
],
},
{
id: "05",
name: "老王",
pid: "01",
job: "测试leader",
children: [
{
id: "13",
name: "小赵",
pid: "05",
job: "测试工程师",
children: [],
},
],
},
{
id: "06",
name: "老李",
pid: "01",
job: "运维leader",
children: [
{
id: "15",
name: "小涛",
pid: "06",
job: "运维工程师",
children: [],
},
],
},
],
},
];
/**
* 利用广度优先遍历实现树到数组
* @param {Array} tree 传出的树
* @return {Array} result 返回结果
*/
function treeToArray(tree) {
//定义返回结果和队列
let result = [],
queue = tree;
//当队列非空时遍历队列
while (queue.length) {
//将当前队列的第一项出队
let target = queue.shift();
result.push({
id: target.id,
name: target.name,
pid: target.pid,
job: target.job,
});
//如果当前项有孩子则循环遍历将孩子加入队尾
if (target.children.length) {
target.children.forEach((item) => {
queue.push(item);
});
}
}
//循环遍历到结束
//返回结果
return result;
}
console.log(treeToArray(newTree));