<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        javascript如何用遞歸寫一個簡單的樹形結構示例

        來源:懂視網 責編:小采 時間:2020-11-27 22:31:09
        文檔

        javascript如何用遞歸寫一個簡單的樹形結構示例

        javascript如何用遞歸寫一個簡單的樹形結構示例:現在有一個數據,需要你渲染出對應的列表出來: var data = [ {id:1}, {id:2}, {id:3}, {id:4}, ]; var str=<ul>; data.forEach(function(v,i){ str+=<li><span>+v.id+<
        推薦度:
        導讀javascript如何用遞歸寫一個簡單的樹形結構示例:現在有一個數據,需要你渲染出對應的列表出來: var data = [ {id:1}, {id:2}, {id:3}, {id:4}, ]; var str=<ul>; data.forEach(function(v,i){ str+=<li><span>+v.id+<

        現在有一個數據,需要你渲染出對應的列表出來:

        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 class='treeName'>"+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 class='myTreeIcon'><input type='radio' name='selectTreeRedio'><span></span></label>",
        
         multi:"<input type='checkbox' name='selectTreeRedio'>"
         }
        
        
         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 class='treeName'>"+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
         }
        

        現在我們已經實現了將沒有層級結構的數組轉化為帶有層級的數組,那么問題來了,樹形圖還常常會需要帶搜索功能,有沒有辦法把帶層級結構的數組轉化為不帶層級結構的一個數組呢?因為如果不帶層級的話,進行搜索等操作時就非常方便,一個filter基本就可以搞定了。

         var jsonToArray=function (nodes) {
         var r=[];
         if (Array.isArray(nodes)) {
         for (var i=0, l=nodes.length; i<l; i++) {
         r.push(nodes[i]);
         if (Array.isArray(nodes[i]["children"])&&nodes[i]["children"].length>0)
         //將children遞歸的push到最外層的數組r里面
         r = r.concat(jsonToArray(nodes[i]["children"]));
         delete nodes[i]["children"]
         }
         } 
         return r;
         }

        這樣,不管后臺返回什么格式給我們,我們都可以自由的互轉了,不管是帶層級的轉不帶層級的,還是把不帶層級的轉化為帶有層級的,都只需要調用一個函數就可以輕松解決。

        不過這里有一個隱患,就是由于對象的引用關系,操作后雖然返回了我們需要東西,但是會改變原來的數據。

        為了不影響到原來的數據,我們需要復制一份數據,需要進行一次深拷貝。

        為什么是深拷貝而不是淺拷貝?因為淺拷貝只會復制最外面的一層,假入某一個key值里面又是一個對象,那對復制后的對象的這個key的值進行操作通用會影響到原來的對象。淺拷貝的方法有很多,ES6的assign,jq第一個參數不為true的 $.extend(),數組的slice(0),還有很多很多。

        對于標準的json格式的對象,可以用JSON.parse(JSON.stringify(obj))來實現。當然,本文寫的是遞歸,所以還是來手寫一個

        function deepCopy(obj){
         var object;
         if(Object.prototype.toString.call(obj)=="[object Array]"){ 
         object=[];
         for(var i=0;i<obj.length;i++){
         object.push(deepCopy(obj[i]))
         } 
         return object
         }
        
         if(Object.prototype.toString.call(obj)=="[object Object]"){ 
         object={};
         for(var p in obj){
         object[p]=obj[p]
         } 
         return object
         }
         }
        

        其實有點類似于淺拷貝,淺拷貝會復制一層,那么我們判斷某個值是對象,通過遞歸再來一次(好比飲料中獎再來一瓶一樣,如果中獎了,就遞歸再來一瓶,又中獎就又遞歸再來一瓶,直到不再中獎),也就是說我們通過無盡的淺拷貝來達到復制一個完全的新的對象的效果。

        這樣,對樹結構操作時,只需要傳入深拷貝后新對象,就不會影響原來的對象了;

        jsonToArray(deepCopy(data));

        亦或是

        arrayToJson(deepCopy(data)):

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        javascript如何用遞歸寫一個簡單的樹形結構示例

        javascript如何用遞歸寫一個簡單的樹形結構示例:現在有一個數據,需要你渲染出對應的列表出來: var data = [ {id:1}, {id:2}, {id:3}, {id:4}, ]; var str=<ul>; data.forEach(function(v,i){ str+=<li><span>+v.id+<
        推薦度:
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: a级毛片无码免费真人久久| 国产精品亚洲精品久久精品 | 国产V亚洲V天堂无码久久久| 男女作爱免费网站| 亚洲成a人片在线观看老师| 日日摸夜夜添夜夜免费视频| 亚洲av无码成人精品区| 免费一级毛片在线播放视频免费观看永久 | 亚洲va中文字幕| 免费不卡中文字幕在线| 无遮挡免费一区二区三区| 国产成人亚洲精品91专区手机| 国产精品免费久久久久久久久| 亚洲精品成人片在线观看精品字幕 | 成人毛片18女人毛片免费96| 亚洲av无码兔费综合| 亚洲精品偷拍视频免费观看 | 最近2019年免费中文字幕高清| 亚洲精品国产第1页| 免费无码又爽又刺激聊天APP| 亚洲综合av一区二区三区| 国产成人精品男人免费| 国产精品免费久久| 91亚洲自偷手机在线观看| 成年性生交大片免费看| 一区二区三区免费在线视频 | 国产美女无遮挡免费网站| 一级毛片a女人刺激视频免费 | 亚洲xxxx18| 亚洲午夜精品久久久久久浪潮| a级毛片毛片免费观看永久| 亚洲成a人片在线看| 中文字幕在亚洲第一在线| 成人免费黄色网址| 美女被艹免费视频| 色噜噜综合亚洲av中文无码| 成人免费无码大片A毛片抽搐色欲| 五月天婷婷免费视频| 亚洲国产综合自在线另类| 国产美女无遮挡免费视频网站| 国产精品网站在线观看免费传媒|