查找指定节点 children

// 查找指定节点
findNodeInTreeByCode(tree, target) {
  for (const node of tree) {
    if (node.id === target) {
      return node;
    }
    if (node.children && node.children.length > 0) {
      const foundNode = this.findNodeInTreeByValue(node.children, target);
      if (foundNode) {
        return foundNode;
      }
    }
  }
  return null;
},

查找指定节点的所有叶子节点 children

// 查找指定节点的所有叶子节点
findLeafNodes(tree, target) {
  const targetNode = this.findNodeInTreeByValue(tree, target);
  if (!targetNode) {
    return null;
  }
  const leafNodes = [];
  function traverse(node) {
    if (!node.children || node.children.length === 0) {
      leafNodes.push(node);
    } else {
      for (const child of node.children) {
        traverse(child);
      }
    }
  }
  traverse(targetNode);
  return leafNodes;
},

查找整棵树的所有叶子节点 children

// 查找整棵树的所有叶子节点
findAllLeafNodes(tree) {
  const leafNodes = [];
  function traverse(node) {
    if (!node.children || node.children.length === 0) {
      leafNodes.push(node);
    } else {
      for (const child of node.children) {
        traverse(child);
      }
    }
  }
  for (const node of tree) {
    traverse(node);
  }
  return leafNodes;
},

获取指定节点的所有子孙节点 parentId

/**
 * 获取指定节点的所有子孙节点
 * @param {Array} nodes 节点数组
 * @param {number|string} qingdanid 指定节点 qingdanid
 * @returns {Array} 所有子孙节点
 */
function getDescendants(nodes, id) {
  // 获取该节点的所有子节点
  const childNodes = nodes.filter((n) => n.parentId === id);
  // 如果没有子节点,则返回空数组
  if (childNodes.length === 0) {
    return [];
  }
  // 递归地获取每个子节点的子孙节点,并将它们拼接到当前数组中
  return childNodes.concat(
    childNodes.map((node) => getDescendants(nodes, node.id)).flat(),
  );
}

判断树形结构中的某个节点是否为叶子节点 parentId

/**
 * 判断树形结构中的某个节点是否为叶子节点
 * @param {Object} row 当前行对象
 * @param {Array} arr 要搜索的数组
 * @returns {boolean} true 为叶子节点,false 为非叶子节点
 */
function isTreeLeafNode(row, arr) {
  // 顶层节点
  if (!row.parentId) {
    return false;
  }
  // 在数组中查找该节点的子节点
  const res = arr.find((item) => item.parentId === row.id);
  return !res;
}

查找指定节点的所有父节点 parentId

/**
 * 查找指定节点的所有父节点
 * @param {Array} arr 节点数组
 * @param {string} targetId 目标节点 ID
 * @returns {Array} 所有父节点的 ID 组成的数组
 */
function findParentNodes(arr, targetId) {
  const result = []; // 保存结果的数组

  arr.forEach((node) => {
    if (node.id === targetId && node.parentId !== null) {
      // 如果当前节点就是目标节点且它的父节点不为空,则将父节点 ID 添加到结果数组中
      result.unshift(node.parentId);
      // 递归查找父节点的父节点
      result.unshift(...findParentNodes(arr, node.parentId));
    }
  });

  return result; // 返回结果数组
}

查找树中的第一个叶子节点 children

/**
 * 查找树中的第一个叶子节点
 * @param {Object[]} tree - 树状结构
 * @returns {Object|null} - 第一个叶子节点,如果未找到则返回null
 */
function findFirstLeafNode(tree) {
  // 定义递归函数 traverse,用于深度搜索树的每个节点
  function traverse(node) {
    // 如果当前节点为叶子节点,即没有子节点,则返回该节点
    if (!node.children || node.children.length === 0) {
      return node;
    }
    // 如果当前节点有子节点,则遍历每个子节点,继续递归调用 traverse 函数
    for (const child of node.children) {
      const result = traverse(child);
      // 如果在子节点中找到了第一个叶子节点,则立即返回该节点
      if (result) {
        return result;
      }
    }
  }

  // 外部循环遍历树的根节点
  for (const node of tree) {
    // 对于每个根节点,都调用 traverse 函数来查找第一个叶子节点
    const result = traverse(node);
    // 如果在当前根节点下找到了第一个叶子节点,则立即返回该节点
    if (result) {
      return result;
    }
  }
  return null;
}