前端 遍历树结构数据 方法总结

递归函数,方法一(传数组的)

  MockData = {
        id: 1,
        name: "xiaoming",
        children: [
            {
                id: 2,
                name: "xiaohonng2",
                children: [{ id: 5, name: " xiao5", children: [] }],
            },
            { id: 3, name: " xiao3", children: [] },
            { id: 4, name: " xiao4", children: [] },
        ],
    };

    function tarverse(nodes, id) {
        let result;
        for (let i = 0; i < nodes.length; i++) {
            if (nodes[i].id == id) {
                result = nodes[i];
                return result;
            }
            if (nodes[i].children && nodes[i].children.length > 0) {
                result = tarverse(nodes[i].children, id);
            }
            if (result) return result;
        }
        return result;
    }

    let node = tarverse(MockData, 3);
    console.log(node, "node");

递归函数,方法二(传对象的)

 MockData = {
    id: 1,
    name: "xiaoming",
    children: [
      {
        id: 2,
        name: "xiaohonng2",
        children: [{ id: 5, name: " xiao5", children: [] }],
      },
      { id: 3, name: " xiao3", children: [] },
      { id: 4, name: " xiao4", children: [] },
    ],
  };

  function tarverse(nodes, id) {
    let result = null;
    console.log(nodes)
    if (nodes.id == id) {
      result = nodes
      return result
    }
    if (nodes.children && nodes.children.length > 0) {
      for (let i = 0; i < nodes.children.length; i++) {
        result = tarverse(nodes.children[i], id)
        if (result) return result
      }
    }
    return result
  }

  let node = tarverse(MockData, 3);
  console.log(node, "node");

封装递归函数,方法三(传对象的)

const traverse = (data, fn, childName = "children") => {
   if(fn(data)== false) {
        return false
   }
    if (data && data[childName]) {
      for(let i = 0; i < data[childName].length; i++) {
        if(!traverse(data[childName][i], fn, childName))  return false
      } 
    }
    return true;
  };

----------------------------------     以上是新版,下面的就不要看了     ---------------------------------------------

业务中,遍历一个东西,经常是,拿到一个对象,遍历他的一个 数组属性。 

因为,遍历几乎都是针对数组的,只有数组,才会存放很多东西,需要遍历。

const traverse = (data, fn, childName = "children") => {
  fn(data);
  if (data && data[childName].length > 0) {
    for(let i = 0; i < data[childName].length; i++) {
        traverse(data[childName][i], fn, childName);
    }
  }
};

递归:

// dataTree 是 对象 childre 是数组
// *这个方法递归的现象是:  把第一个元素递归出来,然后再第一个元素的第一个子元素再递归出来,总之,看下面
//  1  1.1  1.1.1   1.1的子节点递归完了,就  1.1 1.1.2 1.1.2.1 。  即先把第一个尾部子节点,先递归出来。? 
function bianli_digui(dataTree,childrenName = "children") { 
      



  for (let i = 0; i < dataTree.length; i++) {

            if (dataTree[childrenName]&&dataTree[childrenName].length>0){
                    bianli_digui(dataTree[childrenName],childrenName)
                    
            }
        }
}

待测试 

方法二: 递归遍历,且可以传入Fn,不用,去改变里面的数组

var traverse = function traverse(data, fn, childrenName = "children") {
    if (fn(data) === false) {
        return false;
    }

    if (data && data[childrenName]) {
        for (var i = 0 ; i <= data[childrenName].length - 1; i++) {
            if (!traverse(data[childrenName][i], fn, childrenName)) return false;
        }
    }
    return true;
};

注意了: 这里很重点,也是我想了很久才想到的。

tip:1. 之前发现这个是全递归,怎么中途找到想到的数据就结束呢?

2.  里面的return false 和 return true 有什么用,你会发现,你把全部return false删除掉也能 正常使用这个函数。 

总结: 如果要找到数据,就推出整个递归循环,那么就要,你的Fn函数,最后返回 false就行了。

为什么: 1. fn(data)返回false,就进入了 if(fn(data)===false){ return false } 里面。

然后推出当前的递归,。 

2. 退出当前递归后,来到 if(!traverse(xxxx))这里,如果为真,又return false,那么又退出当前递归。 然后如此循环,就会推出整个递归。

这里是工作中实际应用,   拿新的tree的数据, 用两个递归把 这个旧的tree 改成 新的tree

 
   //* 拷贝并递归修改文件树数据,用res.Tree的结构   用DirectoryTree的数据
 let My_DirectoryTree = _.cloneDeep(DirectoryTreeDatas)
 CMFunc.traverseTree(res.Data, (resTree) => {
          CMFunc.traverseTree(My_DirectoryTree, (myTree) => {
            if (myTree.id === resTree.id) {
              for (let key of Object.keys(myTree)) {
                if (key == "content") {
                  resTree[key] = myTree[key]
                }
              }
            }
          })
        })

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值