Get the Tree Menu Node Path

Question

There is a tree structure menu that supports unlimited nesting levels. It is necessary to obtain the path of the node where the submenu is located according to a certain submenu that the user clicks, which is similar to the breadcrumb effect.

A qualified tree menu data structure

const menu = [
  {
    id: "1",
    label: "Level 1",
    children: [
      {
        id: "11",
        label: "Level 2 1-1",
        children: [
          {
            id: "111",
            label: "Level 3 1-1-1",
          },
        ],
      },
    ],
  },
  {
    id: "2",
    label: "Level 1 2",
    children: [
      {
        id: "21",
        label: "Level 2 2-1",
        children: [
          {
            id: "211",
            label: "Level 3 2-1-1",
          },
        ],
      },
      {
        id: "22",
        label: "Level 2 2-2",
        children: [
          {
            id: "221",
            label: "Level 3 2-2-1",
          },
        ],
      },
    ],
  },
  {
    id: "3",
    label: "Level 1 3",
    children: [
      {
        id: "31",
        label: "Level 2 3-1",
        children: [
          {
            id: "311",
            label: "Level 3 3-1-1",
          },
        ],
      },
      {
        id: "32",
        label: "Level 2 3-2",
        children: [
          {
            id: "321",
            label: "Level 3 3-2-1",
          },
        ],
      },
    ],
  },
];

Solution

Analysis:

Recurse the entire tree menu, record the current path name each time it loops, and concatenate all the node names after matching.

One of the key processing points is that every time you loop to the same level array, you need to start recording the path again, otherwise the path will be repeated.

Code:

/**
 * @param {array[][]} data the entire menu array
 * @param {object[][]} v current node object
 * @return {string[]} The path of the current node object
 */

function findPath(data, v) {
  var find = false; //Mark after finding id, end recursion
  var paths = [];

  findId(data, v.id);

  return paths.join("/");

  function findId(root, vid) {
    var currentPathsLength = paths.length;

    root.forEach((ele, i, root) => {
      //Has been found, no need to deal with the following logic
      if (find) {
        return;
      }

      // Loop to the same level array each time and start recording the path again
      paths = paths.slice(0, currentPathsLength);
      paths.push(ele.label);

      // Find and return
      if (ele.id === vid) {
        find = true;
        return;
      } else if (Array.isArray(ele.children) && ele.children.length > 0) {
        //Continue to find child nodes
        return findId(ele.children, vid);
      }
    });
  }
}

Online Demo:

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

Comments