当前位置:   article > 正文

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

前端遍历树结构

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

  1. MockData = {
  2. id: 1,
  3. name: "xiaoming",
  4. children: [
  5. {
  6. id: 2,
  7. name: "xiaohonng2",
  8. children: [{ id: 5, name: " xiao5", children: [] }],
  9. },
  10. { id: 3, name: " xiao3", children: [] },
  11. { id: 4, name: " xiao4", children: [] },
  12. ],
  13. };
  14. function tarverse(nodes, id) {
  15. let result;
  16. for (let i = 0; i < nodes.length; i++) {
  17. if (nodes[i].id == id) {
  18. result = nodes[i];
  19. return result;
  20. }
  21. if (nodes[i].children && nodes[i].children.length > 0) {
  22. result = tarverse(nodes[i].children, id);
  23. }
  24. if (result) return result;
  25. }
  26. return result;
  27. }
  28. let node = tarverse(MockData, 3);
  29. console.log(node, "node");

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

  1. MockData = {
  2. id: 1,
  3. name: "xiaoming",
  4. children: [
  5. {
  6. id: 2,
  7. name: "xiaohonng2",
  8. children: [{ id: 5, name: " xiao5", children: [] }],
  9. },
  10. { id: 3, name: " xiao3", children: [] },
  11. { id: 4, name: " xiao4", children: [] },
  12. ],
  13. };
  14. function tarverse(nodes, id) {
  15. let result = null;
  16. console.log(nodes)
  17. if (nodes.id == id) {
  18. result = nodes
  19. return result
  20. }
  21. if (nodes.children && nodes.children.length > 0) {
  22. for (let i = 0; i < nodes.children.length; i++) {
  23. result = tarverse(nodes.children[i], id)
  24. if (result) return result
  25. }
  26. }
  27. return result
  28. }
  29. let node = tarverse(MockData, 3);
  30. console.log(node, "node");

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

  1. const traverse = (data, fn, childName = "children") => {
  2. if(fn(data)== false) {
  3. return false
  4. }
  5. if (data && data[childName]) {
  6. for(let i = 0; i < data[childName].length; i++) {
  7. if(!traverse(data[childName][i], fn, childName)) return false
  8. }
  9. }
  10. return true;
  11. };

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

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

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

  1. const traverse = (data, fn, childName = "children") => {
  2. fn(data);
  3. if (data && data[childName].length > 0) {
  4. for(let i = 0; i < data[childName].length; i++) {
  5. traverse(data[childName][i], fn, childName);
  6. }
  7. }
  8. };

递归:

  1. // dataTree 是 对象 childre 是数组
  2. // *这个方法递归的现象是: 把第一个元素递归出来,然后再第一个元素的第一个子元素再递归出来,总之,看下面
  3. // 1 1.1 1.1.1 1.1的子节点递归完了,就 1.1 1.1.2 1.1.2.1 。 即先把第一个尾部子节点,先递归出来。?
  4. function bianli_digui(dataTree,childrenName = "children") {
  5. for (let i = 0; i < dataTree.length; i++) {
  6. if (dataTree[childrenName]&&dataTree[childrenName].length>0){
  7. bianli_digui(dataTree[childrenName],childrenName)
  8. }
  9. }
  10. }
  11. 待测试

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

  1. var traverse = function traverse(data, fn, childrenName = "children") {
  2. if (fn(data) === false) {
  3. return false;
  4. }
  5. if (data && data[childrenName]) {
  6. for (var i = 0 ; i <= data[childrenName].length - 1; i++) {
  7. if (!traverse(data[childrenName][i], fn, childrenName)) return false;
  8. }
  9. }
  10. return true;
  11. };

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

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

  1. //* 拷贝并递归修改文件树数据,用res.Tree的结构 用DirectoryTree的数据
  2. let My_DirectoryTree = _.cloneDeep(DirectoryTreeDatas)
  3. CMFunc.traverseTree(res.Data, (resTree) => {
  4. CMFunc.traverseTree(My_DirectoryTree, (myTree) => {
  5. if (myTree.id === resTree.id) {
  6. for (let key of Object.keys(myTree)) {
  7. if (key == "content") {
  8. resTree[key] = myTree[key]
  9. }
  10. }
  11. }
  12. })
  13. })

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号