在javascript中以數組鏈表法實現下拉樹

來源:互聯網
上載者:User

在網頁開發中,大部分的下拉式功能表都是一行一項並且上下對齊,這樣雖然很好但是缺乏階層感,客戶不知道各個選項之間的關係,因此有的時候我們需要在下拉式功能表中以樹形結構展示下拉項,給客戶更好的體驗。比如:假設資料庫中有張表存放了中國省市資訊,如下所示:

這張表是符合樹形結構特徵的,它的樹形結構如右圖所示,相信很多表都有這樣的特徵,這種結構的表以下拉樹展示最好不過了,使用者可以直接看出選項之間的關係。

javascript實現樹形結構應該有很多種方法,我也不知道那些方法都是如何?的,也不想從網上下載現成的,因此決定自己寫一個,剛開始沒什麼頭緒,後來突然靈光一現,想到了數組鏈表的方法,大概思路如下,先上圖:

<img width="" height="" " src="http://img.ddvip.com/2014/0819/201408190841349030.jpg" />

上面這幅圖是樹形結構在數組中的儲存形式,每個節點以對象的形式存放在數組中,每個對象都有一個“array”屬性,它是一個數組,指向它的所有子節點,"array"非常重要,樹形結構的所有操作都要用到它,特別是對樹的遍曆,可以說是這個屬性使多個數組組合起來形成一棵樹,只不過這棵樹是在記憶體中是無形的,我把它理解為“抽象樹(我只是瞎說啊,僅是個人叫法,沒有任何根據)”,是不是有點數組鏈表的味道啊?為了把它變為有形的樹,我們可以對它進行遍曆,在遍曆的時候產生適當的html標籤,最後產生樹的完整html代碼。

下面介紹一下實現過程:

首先,把資料庫中的表以對象的形式儲存在數組裡面,怎麼儲存我就不說了,不是本文重點,為了簡單我直接定義好一個數組,代碼如下:

//為了方便處理,表中每一行的資訊以對象的形式存放在數組中var array = [            {id: 0,parentId: -1,name: "China" },{id: 1, parentId:0,name: "HeNan"},{id: 2, parentId:1, name:"LuoYang"},            {id: 3,parentId: 1,name: "ZhengZhou" },{id: 4,parentId: 0,name: "HeBei" },{id: 5,parentId: 4,name: "TangShang" },            {id: 6,parentId: 4,name: "ShiJiangZhuang" },{id: 7,parentId: 0,name: "HeiLongJiang" },{id: 8,parentId: 7,name: "Haerbin" },            {id: 9,parentId: 7,name: "DaQing" },{id: 10,parentId: 0,name: "GuangDong" },{id: 11,parentId: 10,name: "GuangZhou" },            {id: 12,parentId: 10,name: "FoShan" },{id:13,parentId:1,name:"KaiFeng"},{id:14, parentId: 2, name:"RuYang"},            {id:15,parentId:0,name:"meself"},{id:16,parentId:-1,name:"America"},{id:17,parentId:16,name:"Maiami"},        {id:18,parentId:17,name:"Heat"}        ];

然後,對這個數組進行處理,給每個對象添加“level”屬性,為了方便處理把數組按照對象的“level”屬性從小到大進行排序,並給數組中每個對象添加最重要的"array”屬性,然後遍曆樹產生樹的html,代碼如下:

//給數組中的對象添加"level"屬性        this.initLevel = function(){                for(var i=0; i<this.array.length;i++)                {                    this.level = 0;  //計算每個節點的層次之前,先重設為0                    this.getLevel(this.array[i].id);                    this.array[i].level = this.level;                }            }    //計算每個節點的層次this.getLevel = function (id)        {            if(!Boolean(this.array[id])||id==-1)            {                //alert("The id "+ id +" is not included in array!");                return false;            }                if(this.array[id].id!=-1)            {                this.level = this.level + 1;                //var iidd = this.array[id].parentId;                //arguments.callee(iidd);                this.getLevel(this.array[id].parentId);            }            }    //初始化抽象樹,處理根節點(支援多個根節點的情況,即:多棵樹)//查看本欄目更多精彩內容:http://www.bianceng.cnhttp://www.bianceng.cn/webkf/script/         this.initAbstructTree = function ()         {             var rootCount = 0;             //array_1為全域變數             array_1 = new Array(1);             //shaobing = shaobing + 1;             for(var i=0;i<this.array.length;i++)             {                 if(this.array[i].level==1)                 {                     rootCount++;                     array_1[i] = this.array[i];                     //shaobing = shaobing + 1;                 }                 else                    break;             }         }            //建立抽象樹,用遞迴的方式處理根結點以外的所有節點,以數組的形式建立樹形結構        this.createAbstructTree = function (arrayn)        {            //儲存現在正在遍曆array數組中的第幾層            var layer = arrayn[0].level + 1;            if(layer>this.array[this.array.length-1].level)                return;                for(var i=0;i<arrayn.length;i++)            {                  for(var j=0;j<this.array.length;j++)                  {                      if(this.array[j].level>layer)                          break;                      if(this.array[j].level == layer&&this.array[j].parentId == arrayn[i].id)                      {                          if(!Boolean(arrayn[i].array))                          {                              arrayn[i].array = new Array();                          }                          arrayn[i].array.push(this.array[j]);                      }                  }                  if(Boolean(arrayn[i].array))                  {                      this.createAbstructTree(arrayn[i].array);                  }                }        }                //按照數組中儲存的抽象樹形結構,遞迴產生樹形結構的html        this.generateTreeHtml = function (arrayn,signalArray)        {            for(var i=0;i<arrayn.length;i++)            {                if(arrayn[i].level == 1)   //根節點                {                    if(i == (arrayn.length-1)) //第一層的最後一個節點的表徵圖不一樣                    {                        this.html += "<div><div id='level"+arrayn[i].level+"_"+arrayn[i].id+"'><img src=\"images/Lminus.png\"><img src=\"images/openfoldericon.png\"><span>"+arrayn[i].name+"</span></div>";                    }                    else                        this.html += "<div><div id='level"+arrayn[i].level+"_"+arrayn[i].id+"'><img src=\"images/Tminus.png\"><img src=\"images/openfoldericon.png\"><span>"+arrayn[i].name+"</span></div>";                        //控制標籤的顯示,如果有子節點,則將所有的子節點放在<div>標籤裡面                    if(Boolean(arrayn[i].array))                    {                        this.html += "<div>"                    }                        if(i == (arrayn.length-1))                    {                        if(Boolean(arrayn[i].array))  //有子節點                        {                            signalArray.push("blank");                            this.generateTreeHtml(arrayn[i].array,signalArray);                            signalArray.pop();                        }                        }                    else                    {                        if(Boolean(arrayn[i].array))  //有子節點                        {                            signalArray.push("I");                            this.generateTreeHtml(arrayn[i].array,signalArray);                            signalArray.pop();                        }                        }                        if(Boolean(arrayn[i].array))                    {                        this.html += "</div></div>"; //結束標籤                    }                    else                        this.html += "</div>"; //結束標籤                }                else    //非根節點                {                    //添加對應的外層圖片                    var outerbiaoqian="";                    var innerbiaoqian="";                    if(signalArray.length>0)                    {                            for(var k=0; k<signalArray.length;k++)                        {                            outerbiaoqian += "<img src='images/"+signalArray[k]+".png'>"                        }                    }                        //添加自己的圖片                    if(i == arrayn.length-1) //最後一個節點                    {                        if(Boolean(arrayn[i].array))                        {                            //並且有子節點                            innerbiaoqian+="<img src='images/Lminus.png'><img src='images/openfoldericon.png'>";                            //signalArray.push("blank");                        }                        else                        {                            //沒有子節點                            innerbiaoqian+="<img src='images/L.png'>";                            //signalArray.push("blank");                        }                        }                    else  //不是最後一個節點                    {                        if(Boolean(arrayn[i].array))                        {                            //並且有子節點                            innerbiaoqian+="<img src='images/Tminus.png'><img src='images/openfoldericon.png'>";                        }                        else                        {                            //沒有子節點                            innerbiaoqian+="<img src='images/T.png'>";                        }                        }                            if(Boolean(arrayn[i].array))  //有子節點                    {                        this.html += "<div id='level"+arrayn[i].level+"_"+arrayn[i].id+"'>"+outerbiaoqian+innerbiaoqian+"<span>"+arrayn[i].name+"</span></div><div>";                        if(i == arrayn.length-1) //最後一個節點                        {                            signalArray.push("blank");                        }                        else                            signalArray.push("I");                        this.generateTreeHtml(arrayn[i].array,signalArray);                        signalArray.pop();                        this.html += "</div>";                    }                    else   //沒有子節點                        this.html += "<div id='level"+arrayn[i].level+"_"+arrayn[i].id+"'>"+outerbiaoqian+innerbiaoqian+"<span>"+arrayn[i].name+"</span></div>";                    }            }        }    //調用此方法建立樹形結構,在這個方法裡依次調用上面的方法完成樹的建立        this.createTree = function ()        {            //this.array = array;            this.initLevel(); //add property named level to all the object            this.array.sort(this.compare("level")); //sort the array according to the object's property of level            this.initAbstructTree();            this.createAbstructTree(array_1); //執行完這個方法後,數組array_1就儲存了樹形結構的資訊,即:array_1是抽象樹的根            this.generateTreeHtml(array_1,this.signalArray);            $("#tree").html(this.html);            this.success = true;                tree_additionalFunction();        }        }                //建立出樹形結構以後,給樹增加一些事件和樣式        function tree_additionalFunction()        {            //添加滑鼠經過時的樣式            $("div[id^=level]").hover(function(){                    $(this).addClass("dd");               },function(){                    $(this).removeClass("dd");            });                //點擊結點時擷取結點的值,然後使樹不可見            $("div[id^=level]").click(function(){                   $("#sele").val($(this).find("span").text());                //alert($(this).find("span").text());               $("#tree").slideUp();            });                //展開和收合結點時替換相應的表徵圖            $("div[id^=level]>img").click(function(){                if(this.nodeName == "IMG")                {                    var temp = this.src.split('/');                    var index = temp.length-1;                        if(temp[index] == "Tminus.png" || temp[index] == "Lminus.png")                    {                        //左邊的運算式先去掉路徑中最後一個值,即:要被替換的圖片名                        temp.pop() == "Tminus.png"?this.src = temp.join('/')+"/Tplus.png":this.src = temp.join('/')+"/Lplus.png";                            //替換檔案夾表徵圖                        $(this).next().attr("src",temp.join('/')+"/foldericon.png");                            $(this).parent().next().slideUp();                        return false;                    }                    else if(temp[index] == "Tplus.png" || temp[index] == "Lplus.png")                    {                        //左邊的運算式先去掉路徑中最後一個值,即:要被替換的圖片名                        temp.pop() == "Tplus.png"?this.src = temp.join('/')+"/Tminus.png":this.src = temp.join('/')+"/Lminus.png";                            //替換檔案夾表徵圖                        $(this).next().attr("src",temp.join('/')+"/openfoldericon.png");                            $(this).parent().next().slideDown();                        return false;                    }                }            }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.