当前位置: 首页 > Web前端 > HTML5

如何在javascript中用递归写一个简单的树结构例子

时间:2023-04-05 00:57:48 HTML5

现在有一个数据,需要渲染对应的列表:vardata=[{"id":1},{"id":2},{"id":3},{"id":4},];varstr="

    ";data.forEach(function(v,i){str+="
  • "+v.id+"
  • "})str="
"$(文档).追加(海峡);哼,轻松!说完,另一个问题来了!哦,我带了一个儿子过来帮忙。我循环一个循环一个循环轻松把你带走vardata2=[{"id":1,children:[{"id":"child11"},{"id":"child12"}]},{"id":2},{"id":3children:[{"id":"child31"},{"id":"child32"}]},{"id":4},];varstr="
    ";data2.forEach(function(v,i){if(v.children&&v.children.length>0){str+="
  • "+v.id+"";str+="
      ";v.children.forEach(function(value,index){str+="
    • "+value.id+"";})str="
    ";str="
  • ";}else{str+="
  • "+v.id+"
  • "}})str="
"$(文档)。追加(海峡);还有谁?varjson=[{name:123,id:1children:[{name:453,id:456,children:[{name:789,id:777,children:[{name:"hahahqqq---qq",id:3232,children:[name:'son',id:"13132123211"]}]}]},{name:"Cessihshis",id:12121}]},{name:"Ahhh11",id:12},];还带着全家人来看我回收回收大法。嗯,不知道他家几代同住一个屋檐下,我要骑几次呢?突然间,你觉得自己有一场比赛。正想着,突然有人拍了拍你的肩膀,兄弟,我这里有一本递归秘籍,我看你骨头真厉害,你是武林奇才,我10块钱卖给你。functionrender(treeJson){if(!Array.isArray(treeJson)||treeJson.length<=0){return""}varul=$("
    ");treeJson.forEach(function(item,i){varli=$("
  • "+item.name+"
  • ");if(Array.isArray(item.children)&&item.children.length>0){li.append(render(item.children))}ul.append(li);})返回ul}$(document).append(render(json));,不需要判断数据有多少层。只要当前数组有子数组且长度大于0,该函数就会递归调用自身并返回一个ul。这样就生成了一个很简单的树,但是通常树都有一个radio或者checkbox选择框,很多时候需要扩展树的右侧,比如添加一些new,edit等按钮,您可以考虑传递一个额外的对象作为参数。varcheckbox={radio:"",multi:""}functionrender(treeJson,option={type:0,expandDom:function(){}}){if(!Array.isArray(treeJson)||treeJson.length<=0){返回“”}var{type,expandDom}=选项;varul=$("
      ");treeJson.forEach(function(item,i){varstr="";if(type==1){str+=checkbox.multi}elseif(type==2){str+=checkbox.radio}varli=$(""+str+""+item.name+"");expandDom&&expandDom(li,item);if(item.children&&item.children.length>0){li.append(render(item.children,option))}ul.append(li);})returnul}//option使用默认对象,默认为不需要选择框,也不需要扩展。如果传入的type是1或者2,会生成一个checkbox或者radio,因为radio样式比较丑,用label包裹起来,模拟选中的效果;如果传入扩展参数,则传入当前父li和当前参数,扩大$("#tree").append(render(json,{type:1,expandDom:function(el,data){el.append("")}}))有时候后台返回的可能不是组装好的图层数组,而是所有带pid标识的数组集合,例如:vardata=[{"id":2,"name":"firstlevel1","pid":0},{"id":3,"name":"secondlevel1","pid":2},{"id":5,"name":"三级1","pid":4},{"id":100,"name":"三级2","pid":3},{"id":6,"name":"第三级2","pid":3},{"id":601,"name":"第三级2","pid":6},{"id":602,"name":"第三级2","pid":6},{"id":603,"name":"第三级2","pid":6}];为了使用递归来渲染树,我们需要手动安装层次结构:functionarrayToJson(treeArray){varr=[];vartmpMap={};for(vari=0,l=treeArray.length;i0)//递归将children压入最外层数组rr=r.concat(jsonToArray(nodes[i][“孩子们”]));deletenodes[i]["children"]}}returnr;}这样无论后台返回给我们什么格式,我们都可以自由相互转换,不管是从分层到非分层,还是从非分层到分层,只调用一个函数就可以轻松解决。但是,这里有一个隐患,就是由于对象的引用关系,虽然操作后返回了我们需要的东西,但是原来的数据会被改变。为了不影响原来的数据,我们需要对数据做一份拷贝,这就需要深拷贝。为什么深拷贝而不是浅拷贝?因为浅拷贝只会复制最外层,如果某个对象插入了某个键值,那么对复制对象的键值的一般操作都会影响到原对象。有很多浅拷贝方法,ES6assign,第一个参数不为真的jq$.extend(),数组slice(0)等等。对于标准json格式的对象,可以使用JSON.parse(JSON.stringify(obj))来实现。当然,这篇文章讲的是递归,那我们就写一个函数deepCopy(obj){varobject;if(Object.prototype.toString.call(obj)==[objectArray]"){object=[];对于(vari=0;i