实时获取树形菜单节点路径

问题

现有一个树形结构的菜单,支持无限的嵌套层级,需要根据用户点击的某个子菜单,获取到这个子菜单所在节点的路径,类似于面包屑效果。

一个合格的树形菜单数据结构

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);
      }
    });
  }
}

在线演示:

https://codepen.io/dushusir/pen/zYKeVJe

评论