测试数据:
let tree = [
{
id: '1',
pkId: '',
title: '北京',
children: [
{
id: '1-1',
title: '昌平区',
pkId: '1',
children: [
{
id: '1-1-1',
pkId: '1-1',
title: '沙河镇',
children: []
},
{
id: '1-2-1',
pkId: '1-1',
title: '天通苑',
children: []
}
]
},
{
id: '1-2',
pkId: '1',
title: '海淀区',
children: []
}
]
},
{
id: '2',
pkId: '',
title: '上海',
children: [
{
id: '2-1',
pkId: '2',
title: '黄浦区',
children: []
},
{
id: '2-2',
pkId: '2',
title: '虹口区',
children: []
}
]
},
{
id: '3',
pkId: '',
title: '广东',
children: [
{
id: '3-1',
pkId: '3',
title: '广州市',
children: []
},
{
id: '3-2',
pkId: '3',
title: '深圳市',
children: [
{
id: '3-2-1',
pkId: '3-2',
title: '罗湖区',
children: [
{
id: '3-2-1-1',
pkId: '3-2-1',
title: '人民路街道',
children: [{
id: '3-2-1-1-1',
pkId: '3-2-1-1',
title: '牛B大厦',
children: []
}]
},
{
id: '3-2-2-1',
pkId: '3-2-1',
title: '和平路街道',
children: []
}
]
},
{
id: '3-2-2',
pkId: '3-2',
title: '福田区',
children: []
}
]
}
]
}
];
第一种,深度遍历( 非递归 ):
// 定义一个空数组 arr,用于存储转换后的扁平数组
let arr = [];
// 定义一个名为 childrenToList 的函数,接收一个参数 treeList
function childrenToList(treeList) {
// 使用扩展运算符将 treeList 复制到一个新数组 newArr
let newArr = [...treeList];
// 使用 while 循环遍历 newArr 中的每个元素
while (node = newArr.shift()) {
// 将当前元素 node 添加到 arr 数组中
arr.push(node);
// 如果当前元素 node 有子节点(children 属性存在),则将子节点添加到 newArr 的开头
node.children && newArr.unshift(...node.children);
}
}
// 调用 childrenToList 函数,将 tree 作为参数传入
childrenToList(tree);
第二种,深度遍历( 递归 ):
// 定义一个名为deepSearch的函数,它接收一个参数treeData
function deepSearch(treeData) {
// 使用forEach方法遍历treeData中的每个元素
treeData.forEach(item => {
// 将当前遍历到的元素item添加到arr数组中
arr.push(item)
// 如果当前元素item有子元素(即children属性存在)
if (item.children) {
// 对item的子元素进行深度搜索
deepSearch(item.children)
}
})
}
// 调用deepSearch函数,并传入treeData作为参数
deepSearch(tree)
第三种, 广度遍历( 非递归 ):
// 定义一个空数组,用于存储遍历到的节点
let arr = [];
// 定义一个函数,名为childrenToList,接收一个参数tree
function childrenToList(tree) {
// 使用扩展运算符将tree的每个节点复制到nodeList数组中
let nodeList = [...tree];
// 当nodeList数组不为空时,循环执行以下操作
while (node = nodeList.shift()) {
// 将当前节点node添加到arr数组中
arr.push(node);
// 如果当前节点node有子节点
if (node.children) {
// 将node的子节点添加到nodeList数组中
nodeList.push(...node.children);
}
}
}
// 调用childrenToList函数,并将tree作为参数传入
childrenToList(tree);
第四种, 广度遍历( 递归 ):
// 定义一个空数组,用于存储遍历到的节点
let arr = [];
// 定义一个函数,名为childrenToList,接收一个参数treeData
function childrenToList(treeData) {
// 定义一个空数组,用于存储子节点的列表
let childrenList = [];
// 如果treeData数组为空,则直接返回false
if (treeData.length == 0) return false;
// 遍历treeData中的每个元素
treeData.forEach(item => {
// 如果当前元素的pkId为空字符串
if (item.pkId === '') {
// 将当前元素添加到arr数组中
arr.push(item);
}
// 如果当前元素有子元素并且子元素数组不为空
if (item.children && item.children.length) {
// 将当前元素的子元素数组添加到childrenList数组中
childrenList.push(...item.children);
}
});
// 将childrenList数组中的元素添加到arr数组中
arr.push(...childrenList);
// 递归调用childrenToList函数,处理子节点
childrenToList(childrenList);
// 返回arr数组,它包含了从树形结构转换而来的线性列表
return arr;
}
// 调用childrenToList函数,并将treeData作为参数传入
childrenToList(tree);