js处理树形数据

前言

树形结构数据的核心操作是遍历,其次由遍历延伸的一些我们常见的业务操作有:
(1)查找/过滤返回符合条件的节点(返回节点数据)
(2)原结构基础上过滤掉符合条件的节点【删除或者说过滤符合/不符合条件节点】(返回树结构)
(3)树形数据重构【原有树形数据基础上,增加自定义属性/修改原有属性】(返回树结构)
对应1、2、3点的实现方法如下(以下方法均不污染源数据):

1.findNode()

(1)源数据
//扒了elementUI树的数据,反正基本的树形结构)
let myTree = [{
    id: 1,
    label: 'test',
    children: [{
      id: 4,
      label: 'test',
      children: [
	      {
	        id: 9,
	        label: '三级 1-1-1'
	      }, {
	        id: 10,
	        label: 'test'
	      }
      ]
    }]
  }, {
    id: 2,
    label: 'test666',
    children: [
	    {
	      id: 5,
	      label: '二级 2-1'
	    }, {
	      id: 6,
	      label: 'test666'
	    }
    ]
  }, {
    id: 3,
    label: '一级 3',
    children: [
	    {
	      id: 7,
	      label: '二级 3-1'
	    }, {
	      id: 8,
	      label: '二级 3-2'
	    }
    ]
 }],
(2)预期结果
//查找并返回id为7的节点,并返回该节点数据
{
 	id: 7,
  	label: '二级 3-1'
}
(3)方法函数
//--------------核心方法:支持自定义查询条件--------------------
function findNode(tree, func) {
  	for (const node of tree) {
        if (func(node)) return node
        if (node.children) {
            const res = findNode(node.children, func)
            if (res) return res
        }
    }
    return null
}
 //--------------调用--------------
let myNodes = findNode(myTree,(node)=>{
 	return node.id === 7;
})

2.filterTree()

(1)源数据
同上
(2)预期结果
//在源数据的基础上过滤掉所有的label为'test666'的节点(这里根据实际场景,例如节点中包含标记性别的属性gender:0女/1男,可以过滤掉所有属性gender为0或1的节点),并返回一个新的树

[{
  id: 2,
  label: 'test666',
  children: [
   {
     id: 5,
     label: '二级 2-1'
   }, {
     id: 6,
     label: 'test666'
   }
  ]
}]
(3)方法函数
//--------------核心方法--------------
function filterTree(tree, func) {
    return tree.filter(node => {
        return func(node);
    }).map(node => {
        node = Object.assign({}, node)
        if (node.children) {
            node.children = filterTree(node.children, func)
        }
        return node
    })
}
//--------------调用--------------
let newTree = filterTree(myTree,(node)=>{
   return node.label === 'test';
})

3.mapTree()

(1)源数据
同上
(2)预期结果
//具体结果省略......
//总言之就是给每个节点加上一个新的属性check:true(当然,根据实际业务场景或需求也可以做到对节点的属性值进行修改等等操作)
(3)方法函数
//--------------核心方法--------------
function mapTree(tree, func) {
    return tree.map(node => {
        node = Object.assign({}, node)
        node = func(node)
        if (node.children) {
            node.children = mapTree(node.children, func)
        }
        return node
    })
}
//--------------调用--------------
let newTree = mapTree(myTree,(node)=>{
    return {
        ...node,
        checked:true,
    }
})

遍历写法可参考:

https://segmentfault.com/q/1010000040502862/

https://www.cnblogs.com/yanggb/p/12572124.html

https://xie.infoq.cn/article/994044797f1e3c36a2bc796fe

https://www.jb51.net/article/77042.htm

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值