如何对树型结构进行检索


如何对树结构进行检索,并返回完整路径的树结构

近期有个前端需求,用户想要对树进行检索。

需求详情

  • 要展示所有条件匹配的节点
  • 展示到的节点,若还具有子节点,默认不展开。用户可以继续点击展开查看。

需求分析

  1. 找到符合条件的节点,并且

代码示例

以简单的三层结构为示例

  const treeData = [
  {
    name: '示例A',
    parantId: null,
    id: 1,
    children: [{
      name: '示例AA',
      parantId: null,
      id: 11,
      children: [{
        name: '示例AAA',
        parantId: null,
        id: 111,
        children: []
      }]
    }]
  },
  {
    name: '示例A1',
    parantId: null,
    id: 2,
    children: [{
      name: '示例AA1',
      parantId: null,
      id: 22,
      children: [{
        name: '示例AAA1',
        parantId: null,
        id: 222,
        children: []
      }]
    }]
  }
]

const keyword = 'AAA1'

const getTree = (treeData, keyword) => {
  let nodes = []
  let openKey = []
  for (let i = 0; i < treeData.length; i++) {
    const node = treeData[i]
    // 匹配上了。不需要子节点返回了,只需要子节点需要展开到哪里, 储存展开的节点
    const { nodes: _nodes, openKey: _openKey } = getTree(node.children, keyword)
    if (node.name.includes(keyword)) {
      // 需要包含子节点所以储存含子节点的整个节点
      nodes.push(node)
      // 若不需要包含子节点
      // nodes.push({
      //   ...node,
      //   children: []
      // })
      
      // 若子元素包含匹配的、需要展开自身
      if (nodes && nodes.length) {
        openKey = _openKey.concat([node.id])
      }
    } else {
      // 若子节点含匹配的则保存该节点
      if (_nodes && _nodes.length) {
        // 需要包含被过滤后的子节点
        nodes.push({
          ...node,
          children: _nodes
        })
        // 给节点加上展开标识
        if (nodes && nodes.length) {
          openKey = _openKey.concat([node.id])
        }
      }
    }
  }
  return { nodes, openKey }
}

// 测试一下
getTree(treeData, keyword)

// 结果
{
  nodes: [{
    name: '示例A1',
    parantId: null,
    id: 2,
    open: true,
    children: [{
      name: '示例AA1',
      parantId: null,
      id: 22,
      open: true,
      children: [{
        name: '示例AAA1',
        parantId: null,
        id: 222,
        children: []
      }]
    }]
  }],
  openKey: [222, 22, 2]
}