实时获取树形菜单节点路径
问题
现有一个树形结构的菜单,支持无限的嵌套层级,需要根据用户点击的某个子菜单,获取到这个子菜单所在节点的路径,类似于面包屑效果。
一个合格的树形菜单数据结构
const menu = [
{
id: "1",
label: "一级 1",
children: [
{
id: "11",
label: "二级 1-1",
children: [
{
id: "111",
label: "三级 1-1-1",
},
],
},
],
},
{
id: "2",
label: "一级 2",
children: [
{
id: "21",
label: "二级 2-1",
children: [
{
id: "211",
label: "三级 2-1-1",
},
],
},
{
id: "22",
label: "二级 2-2",
children: [
{
id: "221",
label: "三级 2-2-1",
},
],
},
],
},
{
id: "3",
label: "一级 3",
children: [
{
id: "31",
label: "二级 3-1",
children: [
{
id: "311",
label: "三级 3-1-1",
},
],
},
{
id: "32",
label: "二级 3-2",
children: [
{
id: "321",
label: "三级 3-2-1",
},
],
},
],
},
];
解决方案
思路:
递归整个树形菜单,记录下每次循环时候的当前路径名称,匹配到之后再把所有节点名称拼接起来。
其中有一个关键处理点是每次循环到同级数组,需要重新开始记录路径,否则会出现路径重复的情况
代码:
/**
* @param {array[][]} data 整个菜单数组
* @param {object[][]} v 当前节点对象
* @return {string[]} 当前节点对象路径
*/
function findPath(data, v) {
var find = false; //找到id后标记,结束递归
var paths = [];
findId(data, v.id);
return paths.join("/");
function findId(root, vid) {
var currentPathsLength = paths.length;
root.forEach((ele, i, root) => {
// 后面不再循环找了
if (find) {
return;
}
// 每次循环到同级数组,重新开始记录路径
paths = paths.slice(0, currentPathsLength);
paths.push(ele.label);
// 找到即返回
if (ele.id === vid) {
find = true;
return;
} else if (Array.isArray(ele.children) && ele.children.length > 0) {
//有子节点继续寻找
return findId(ele.children, vid);
}
});
}
}
在线演示:
评论