提示:底部有完整的源码,童鞋们有需要的可以CTRL+C带走,不过我建议大家真正看懂实现原理而不是直接CTRL+C。树是JS中很常见的数据结构。知识库目录、侧边栏菜单、词典目录、企业组织结构等可能会用到树操作,不知道大家有没有用过element-ui等组件库中的级联选择器?它接收的数据类型是一个树结构数组。级联选择器的绑定值是一个选中的父子节点id的数组,后端通常只需要我们提供最后一个叶子节点的id即可;但是,在编辑的时候,我们只提供了最后一个叶子节点的id,id不能恢复级联选择器选项的选中状态;因此,我们需要通过节点id,找出所有与其关联的父节点,得到一个适合级联选择器的数据。现在,我们实现getTreeIds函数,根据节点id找到关联的父节点。我们先定义一个空函数,它需要接收3个参数:树结构数组tree、节点id、节点信息配置config。config用于配置id和children字段,因为这是一个通用的功能,我们需要处理后端开发人员使用的children和id字段可能不一致的情况。exportconstgetTreeIds=(tree,nodeId,config)=>{}以下所有代码都写在getTreeIds函数体中。现在,我们从配置中获取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字段,从而建立子节点与父节点的关联关系。consttoFlatArray=(tree,parentId)=>{returntree.reduce((t,_)=>{constchild=_[children]返回[...t,parentId?{..._,parentId}:_,...(child&&child.length?toFlatArray(child,_[id]):[])]},[])}然后我们创建getIds函数,它接受一个扁平化的树,使用while循环来搜索,如果有parentId,我们将其添加到ids数组的开头并一直搜索到树的根。最后,我们返回ids数组。constgetIds=flatArray=>{letids=[nodeId]letchild=flatArray.find(_=>_[id]===nodeId)while(child&&child.parentId){ids=[child.parentId,...ids]child=flatArray.find(_=>_[id]===child.parentId)}returnids}最后,在getTreeIds函数体的最后,我们将标准树转换成扁平树并传递togetIds返回函数返回的ids数组。返回getIds(toFlatArray(tree))现在,我们完成了。我们可以用一些假数据来测试它:consttreeData=[{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]童鞋们,学到了是简单吗?
