2

JS中树的查找:通过子节点ID查找所有关联的父节点

 2 years ago
source link: https://www.fly63.com/article/detial/11275
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
更新日期: 2022-03-22阅读量: 15标签: 分享

扫一扫分享

树是JS中非常常见的数据结构。知识库目录,侧边栏菜单,字典目录,企业组织架构等都可能会用到树的操作。

不知道大家有没有使用过element-ui等组件库中的级联选择器?它所接收的数据类型就是树形结构的数组。级联选择器的绑定值是被选中的一系列父子节点id构成的数组,而后端通常仅需要我们提供最后一个叶子节点的id;然而,在编辑的时候,我们仅提供最后一个叶子节点的id是无法还原级联选择器选项的选中状态的;所以,我们需要通过该节点id将与其关联的父节点全部查找出来,得到一个与级联选择器适配的数据。

现在,我们实现根据节点id查找关联的父节点函数getTreeIds。我们先定义一个空函数,该函数需要接收3个参数:树形结构数组tree,节点id,节点信息配置config。config用于配置id和children字段,因为这是一个通用函数,我们需要应对后端开发者使用的children和id字段可能存在的不统一问题。

export const getTreeIds = (tree, nodeId, config) => {}

下面的所有代码全部写在getTreeIds函数体内。现在,我们从config中拿到children和id字段,并分别设置一个默认值。

const { children = 'children', id = 'id' } = config || {}

假设我们的数据结构是下面这样的,该如何通过子节点查找父节点呢?我们都知道,父子节点的关联是通过children字段建立的。可惜这个关联是单向的,我们只能通过父节点查找子节点,而不能通过子节点查找父节点,因为我们的子节点缺少对父节点的引用。

[
  {
    id: 1,
    label: 'test1',
    children: [
      {
        id: 2,
        label: 'test1-1',
        children: [ { id: 3,  label: 'test1-1-1'  }]
      }
    ]
  }
]

我们需要编写一个函数手动将子节点与父节点建立绑定。最简单的查找方式就是将树形结构转化为扁平化数组,并建立关联,然后再进行查找。

toFlatArray函数的源码如下,我们使用数组的reduce方法对树形结构数组进行聚合递归转化为扁平化的树,将parentId字段添加到子节点,这样我们就建立了子节点到父节点的关联。

const toFlatArray = (tree, parentId) => {
    return tree.reduce((t, _) => {
      const child = _[children]
      return [
        ...t,
        parentId ? { ..._, parentId } : _,
        ...(child && child.length ? toFlatArray(child, _[id]) : [])]
    }, [])
  }

然后,我们创建getIds函数,该函数接收一个扁平化的树,使用while循环进行查找,如果存在parentId,我们就把它添加到ids数组的开头,一直查找到树的根部。最后,我们返回ids数组。

const getIds = flatArray => {
    let ids = [nodeId]
    let child = flatArray.find(_ => _[id] === nodeId)
    while (child && child.parentId) {
      ids = [child.parentId, ...ids]
      child = flatArray.find(_ => _[id] === child.parentId)
    }
    return ids
  }

最后,我们在getTreeIds函数体的尾部,将标准树转化为扁平化的树后传递给getIds函数返回的ids数组返回。

return getIds(toFlatArray(tree))

现在,我们大功告成了。我们可以用一些假数据测试一下:

const treeData = [
  {
    id: 1,
    label: 'test1',
    children: [
      {
        id: 2,
        label: 'test1-1',
        children: [
          {
            id: 3,
            label: 'test1-1-1'
          },
          {
            id: 4,
            label: 'test1-1-2',
            children: [
              {
                id: 5,
                label: 'test1-1-1-1'
              }
            ]
          }
        ]
      }
    ]
  }
]
console.log(getTreeIds(treeData, 5)) // 输出 [1, 2, 4, 5]
console.log(getTreeIds(treeData, 3)) // 输出 [1, 2, 3]

童鞋们,学会了吗?是不是很简单?

链接: https://www.fly63.com/article/detial/11275


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK