常见的基本结构如下,每个对象包含id, children
tips: 做了一定程度的不返回child操作,没做null 处理, null 值我个人倾向于在全局处理。一般会处理成undefined,其实就是直接删掉。
常见的树结构如下
const tree = [
{
id: 1,
children: [
{
id: 8,
children: []
},
{
id: 2,
children: [
{
id: 3,
children: [
{
id: 11,
children: [
{
id: 12
}
]
},
{
id: 13
},
{
}
]
}
]
},
{
id: 10,
children: [
{
id: 9,
}
]
},
{
id: 4,
children: []
}
]
},
{
id: 5,
children: []
},
{
id: 6,
children: [
{
id: 7,
children: []
}
]
}
]
处理函数
/**
* 根据树结构查找对象
* @param {Array} tree 要遍历的树
* @param {id} id 查找的节点id
* @returns 查找到的路径 path为空数组,表示没找到
*/
const findItem = (tree, id) => {
// 是否找到,flag 要定义在外面,循环里面每次循环会重新赋值,是不对的
let flag = false
// 查找的路径,当前塞的id,也可以往里面塞对象
let path = []
// 定义一个查找函数。递归使用
/**
* 内部真正查找的函数,递归使用
* @param {Array} tree 要遍历的树
* @param {id} id 查找的节点id
* @param {Number} level 上级树级别,默认传的0(看不到的最外层不循环),每循环一层执行加1,
*/
const find = (tree, id, level = 0) => {
level += 1 // level 进行加1操作
// 循环操作
for (let index = 0; index < tree.length; index++) {
// 如果找到了,不再循环,flag 外层定义,会终止所有的循环
if (flag) break
// 当前枝干
const branch = tree[index]
// 操作前,根据当前的level 清空一下,不需要的level,只保留当前level的父级以上的level
path = path.slice(0, level - 1)
// 将当前id加到路径里面,也可以添加对象
path.push(branch.id)
// eslint-disable-next-line
if (branch.id == id) { // 隐式转换,利用一下
flag = true
break // 找到了,就返回
}
// 没找到,如果有children的话,就继续遍历children
const { children = [] } = branch
if (children.length) {
find(children, id, level)
}
}
}
find(tree, id)
if (!flag) path = []
return path
}
复制代码自行尝试。
网友评论