现在有一个数据,需要你渲染出对应的列表出来:
var data = [ {"id":1}, {"id":2}, {"id":3}, {"id":4}, ]; var str="<ul>"; data.forEach(function(v,i){ str+="<li><span>"+v.id+"</span></li>" }) str="</ul>" $(doucment).append(str);
哼,easy!
语罢,又是一道题飞来!
哦,还带了儿子来当帮手。我一个循环再一个循环,轻松带走你们
var data2 = [ {"id":1,children:[{"id":"child11"},{"id":"child12"}]}, {"id":2}, {"id":3children:[{"id":"child31"},{"id":"child32"}]}, {"id":4}, ]; var str="<ul>"; data2.forEach(function(v,i){ if(v.children&&v.children.length>0){ str+="<li><span>"+v.id+"</span>"; str+="<ul>"; v.children.forEach(function(value,index){ str+="<li><span>"+value.id+"</span>"; }) str="</ul>"; str="</li>"; }else{ str+="<li><span>"+v.id+"</span></li>" } }) str="</ul>" $(doucment).append(str);
还有谁?
var json=[ { name:123,id:1 children:[ { 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:"啊啊啊11", id:12 }, ];
竟然把全家都带来了,看我循环循环再循环大法。
嗯,不知道他家几代同堂,我该循环几次?突然间你感觉遇到对手了。
正纳闷着,突然有人拍了一下你的肩膀,兄弟,我这里有一本递归秘籍,我看你骨骼惊奇,是个练武奇才,10块钱卖你了。
function render(treeJson){ if(!Array.isArray(treeJson)||treeJson.length<=0){return ""} var ul=$("<ul>"); treeJson.forEach(function(item,i){ var li=$("<li><span>"+item.name+"</span></li>"); if(Array.isArray(item.children)&&item.children.length>0){ li.append(render(item.children)) } ul.append(li); }) return ul } $(document).append(render(json));
好了不扯了,通过递归,无需再判断数据有多少层级,只有当前数组有children并且长度大于0,函数就会递归调用自身,并且返回一个ul。
这样一来,一颗非常简陋的树就生成了,不过通常树都带有radio或者checkbox选择框,而且很多时候都需要对树的右侧进行拓展,比如加一些新增,编辑等按钮什么的,可以考虑多传一个对象作为参数。
var checkbox={ radio:"<label><input type='radio'><span></span></label>", multi:"<input type='checkbox'>" } function render(treeJson,option={type:0,expandDom:function(){}}){ if(!Array.isArray(treeJson)||treeJson.length<=0){return ""} var {type,expandDom}=option; var ul=$("<ul>"); treeJson.forEach(function(item,i){ var str=""; if(type==1){ str+=checkbox.multi }else if(type==2){ str+=checkbox.radio } var li=$("<li data-id='"+item+"'>"+str+"<span>"+item.name+"</span></li>"); expandDom&&expandDom(li,item); if(item.children&&item.children.length>0){ li.append(render(item.children,option)) } ul.append(li); }) return ul } //option使用了一个默认对象,默认为不需要选择框和不需要拓展, 如果传入的type为1或者2,则生成checkbox或者radio,由于radio样式比较丑,用label包起来自己模拟选中的效果;如果传入拓展参数,则把当前的父级li以及当前的参数传入,以便进行拓展。 $("#tree").append(render(json,{ type:1, expandDom:function(el,data){ el.append("<button>编辑</button><button>测试</button><a data-msg='"+JSON.stringify(data)+"'></a>") } }))
有时候后台返回的可能不是拼装好层级的数组,而是带有pid标识的所有数组的集合,比如:
var data = [ {"id":2,"name":"第一级1","pid":0}, {"id":3,"name":"第二级1","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} ]; 为了用递归来渲染出树来,这时,就需要我们手动来将层级装好了: function arrayToJson(treeArray){ var r = []; var tmpMap ={}; for (var i=0, l=treeArray.length; i<l; i++) { // 以每条数据的id作为obj的key值,数据作为value值存入到一个临时对象里面 tmpMap[treeArray[i]["id"]]= treeArray[i]; } for (i=0, l=treeArray.length; i<l; i++) { var key=tmpMap[treeArray[i]["pid"]]; //循环每一条数据的pid,假如这个临时对象有这个key值,就代表这个key对应的数据有children,需要Push进去 if (key) { if (!key["children"]){ key["children"] = []; key["children"].push(treeArray[i]); }else{ key["children"].push(treeArray[i]); } } else { //如果没有这个Key值,那就代表没有父级,直接放在最外层 r.push(treeArray[i]); } } return r }