多叉樹結(jié)合JavaScript樹形控件實現(xiàn)無限級樹形菜單一種構(gòu)建多級有序樹形結(jié)構(gòu)JSON或XML數(shù)據(jù)源的方法_第1頁
多叉樹結(jié)合JavaScript樹形控件實現(xiàn)無限級樹形菜單一種構(gòu)建多級有序樹形結(jié)構(gòu)JSON或XML數(shù)據(jù)源的方法_第2頁
多叉樹結(jié)合JavaScript樹形控件實現(xiàn)無限級樹形菜單一種構(gòu)建多級有序樹形結(jié)構(gòu)JSON或XML數(shù)據(jù)源的方法_第3頁
多叉樹結(jié)合JavaScript樹形控件實現(xiàn)無限級樹形菜單一種構(gòu)建多級有序樹形結(jié)構(gòu)JSON或XML數(shù)據(jù)源的方法_第4頁
多叉樹結(jié)合JavaScript樹形控件實現(xiàn)無限級樹形菜單一種構(gòu)建多級有序樹形結(jié)構(gòu)JSON或XML數(shù)據(jù)源的方法_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

-.z多叉樹結(jié)合JavaScript樹形控件實現(xiàn)無限級樹形菜單〔一種構(gòu)建多級有序樹形構(gòu)造JSON〔或*ML〕數(shù)據(jù)源的方法〕一、問題研究的背景和意義在Web應用程序開發(fā)領(lǐng)域,基于AJA*技術(shù)的JavaScript樹形控件已經(jīng)被廣泛使用,它用來在Html頁面上展現(xiàn)具有層次構(gòu)造的數(shù)據(jù)項。目前市場上常見的JavaScript框架及組件庫中均包含自己的樹形控件,例如JQuery、Dojo、UI、E*tJS等,還有一些獨立的樹形控件,例如dhtml*tree等,這些樹形控件完美的解決了層次數(shù)據(jù)的展示問題。展示離不開數(shù)據(jù),樹形控件主要利用AJA*技術(shù)從效勞器端獲取數(shù)據(jù)源,數(shù)據(jù)源的格式主要包括JSON、*ML等,而這些層次數(shù)據(jù)一般都存儲在數(shù)據(jù)庫中?!盁o限級樹形菜單〞,顧名思義,沒有級別的限制,它的數(shù)據(jù)通常來自數(shù)據(jù)庫中的無限級層次數(shù)據(jù),這種數(shù)據(jù)的存儲表通常包括id和parentId這兩個字段,以此來表示數(shù)據(jù)之間的層次關(guān)系?,F(xiàn)在問題來了,既然樹形控件的數(shù)據(jù)源采用JSON或*ML等格式的字符串來組織層次數(shù)據(jù),而層次數(shù)據(jù)又存儲在數(shù)據(jù)庫的表中,則如何建立起樹形控件與層次數(shù)據(jù)之間的關(guān)系,換句話說,如何將數(shù)據(jù)庫中的層次數(shù)據(jù)轉(zhuǎn)換成對應的層次構(gòu)造的JSON或*ML格式的字符串,返回給客戶端的JavaScript樹形控件.這就是我們要解決的關(guān)鍵技術(shù)問題。本文將以目前市場上比較熾熱的E*tJS框架為例,講述實現(xiàn)無限級樹形菜單的方法,該方法同樣適用于其它類似的JS樹形控件。E*tJS框架是富客戶端開發(fā)中出類拔萃的框架之一。在E*t的UI控件中,樹形控件無疑是最為常用的控件之一,它用來實現(xiàn)樹形構(gòu)造的菜單。TreeNode用來實現(xiàn)靜態(tài)的樹形菜單,AsyncTreeNode用來實現(xiàn)動態(tài)的異步加載樹形菜單,后者最為常用,它通過接收效勞器端返回來的JSON格式的數(shù)據(jù),動態(tài)生成樹形菜單節(jié)點。動態(tài)生成樹有兩種思路:一種是一次性生成全部樹節(jié)點,另一種是逐級加載樹節(jié)點〔利用AJA*,每次點擊節(jié)點時查詢下一級節(jié)點〕。對于大數(shù)據(jù)量的菜單節(jié)點來說,逐級加載是比較適宜的選擇,但是對于小數(shù)據(jù)量的菜單來說,一次性生成全部節(jié)點應該是最為合理的方案。在實際應用開發(fā)中,一般不會遇到特別大數(shù)據(jù)量的場景,所以一次性生成全部菜單節(jié)點是我們重點研究的技術(shù)點,也就是本文要解決的關(guān)鍵技術(shù)問題。本文以基于E*tJS的應用系統(tǒng)為例,講述如何將數(shù)據(jù)庫中的無限級層次數(shù)據(jù)一次性在界面中生成全部菜單節(jié)點〔例如在界面中以樹形方式一次性展示出銀行所有分支機構(gòu)的信息〕,同時對每一個層次的菜單節(jié)點按照*一屬性和規(guī)則排序,展示出有序的菜單樹。解決一次性構(gòu)造無限級樹形菜單的問題,可以拓展出更多的應用場景,例如樹形構(gòu)造表格TreeGrid,一次性生成樹形表格,對樹形表格進展完整分頁,對表格列進展全排序;或者可以利用本文的思路擴展出其他的更復雜的應用場景。先看兩個圖例,有個直觀上的認識:圖一,銀行分支機構(gòu)樹形構(gòu)造菜單圖二,樹形構(gòu)造表格二、詳細設(shè)計方案讓我們先看兩段代碼片段:文件一,branchTree.html〔E*t樹形控件頁面〕E*t.onReady( function(){ vartree=newE*t.tree.TreePanel({height:300,width:400,animate:true,enableDD:true,containerScroll:true,rootVisible:false,frame:true,//getBranch.do請求效勞器返回多級樹形構(gòu)造的JSON字符串loader:newE*t.tree.TreeLoader({dataUrl:'getBranch.do'}),root:newE*t.tree.AsyncTreeNode({id:'0',te*t:'根結(jié)點'})});tree.e*pandAll();});文件二,branchTreeJSON.jsp〔接收getBranch.do請求,返回多級樹形構(gòu)造的JSON字符串〕<%//讀取銀行分支機構(gòu)的層次數(shù)據(jù)Listresult=DataAccess.getBankInfoList();//將層次數(shù)據(jù)轉(zhuǎn)換為多叉樹對象〔本文下面會詳細介紹該數(shù)據(jù)構(gòu)造的實現(xiàn)方法〕Noderoot=E*tTreeHelper.createE*tTree(result);%>[<%=root.toString()%><!--以JSON的形式返回響應數(shù)據(jù),E*t.tree.TreeLoader會根據(jù)此數(shù)據(jù)生成樹形菜單-->]以上兩個程序文件是一次性生成無限級樹形菜單所必須的,其中最為關(guān)鍵的局部就是如何生成一個無限級的樹形構(gòu)造JSON字符串,返回給客戶端的E*t樹形控件。對于銀行分支機構(gòu)來說,需要返回類似如下的JSON串:{ id:'100000', te*t:'**銀行總行', children:[ { id:'110000', te*t:'**分行', children:[ { id:'113000', te*t:'**銀行開發(fā)區(qū)支行', leaf:true },{ id:'112000', te*t:'**銀行解放道支行', children:[ { id:'112200', te*t:'**銀行三大街支行', leaf:true }, { id:'112100', te*t:'**銀行廣陽道支行', leaf:true } ] }, { id:'111000', te*t:'**銀行金光道支行', leaf:true } ] } ]}同時還需要對樹中每一個層次的節(jié)點按照*一屬性〔比方分支機構(gòu)編號〕進展排序,以展示出有序的樹形菜單?,F(xiàn)在可以把問題概括為:把數(shù)據(jù)庫中的層次數(shù)據(jù)轉(zhuǎn)換成多級樹形構(gòu)造的JSON格式的字符串對樹中每一個層次的節(jié)點按照*一屬性〔比方分支機構(gòu)編號〕進展排序下面介紹解決問題的思路:在數(shù)據(jù)構(gòu)造這門課中,我們都學過樹,無限級樹形菜單就可以抽象成一種多叉樹構(gòu)造,即每個節(jié)點下包含多個子節(jié)點的樹形構(gòu)造,首先就需要把數(shù)據(jù)庫中的層次數(shù)據(jù)轉(zhuǎn)換成多叉樹構(gòu)造的對象樹,也就是構(gòu)造出一棵多叉樹。有了數(shù)據(jù)構(gòu)造,還要實現(xiàn)相應的算法,我們需要實現(xiàn)兩種算法:1、兄弟節(jié)點橫向排序算法,對隸屬于同一個父節(jié)點下面的所有直接子節(jié)點按照*一節(jié)點屬性和規(guī)則進展排序,保持兄弟節(jié)點橫向有序;2、先序遍歷算法,遞歸打印出無限級JSON字符串。概括起來分為三步:構(gòu)造無序的多叉樹構(gòu)造實現(xiàn)兄弟節(jié)點橫向排序方法實現(xiàn)先序遍歷方法,打印出JSON字符串如下列圖:我們給這棵樹起個名字吧,就叫做multipletree

,簡稱M-Tree。三、源代碼實現(xiàn)〔Java語言版〕實現(xiàn)這樣一顆樹,需要設(shè)計三個類:樹類〔MultipleTree.java〕、節(jié)點類〔Node.java〕、孩子列表類〔Children.java〕;為了方便演示,還需要構(gòu)造一些假的層次數(shù)據(jù),因此還需要建一個構(gòu)造假數(shù)據(jù)的類〔VirtualDataGenerator.java〕,以下代碼拷貝出來之后可直接運行測試:packagetest;importjava.util.ArrayList;importjava.util.parator;importjava.util.HashMap;importjava.util.Iterator;importjava.util.List;importjava.util.Map;importjava.util.Set;importjava.util.Collections;/***多叉樹類*/publicclassMultipleTree{ publicstaticvoidmain(String[]args){ //讀取層次數(shù)據(jù)結(jié)果集列表 ListdataList=VirtualDataGenerator.getVirtualResult(); //節(jié)點列表〔散列表,用于臨時存儲節(jié)點對象〕 HashMapnodeList=newHashMap(); //根節(jié)點 Noderoot=null; //根據(jù)結(jié)果集構(gòu)造節(jié)點列表〔存入散列表〕 for(Iteratorit=dataList.iterator();it.hasNe*t();){ MapdataRecord=(Map)it.ne*t(); Nodenode=newNode(); node.id=(String)dataRecord.get("id"); node.te*t=(String)dataRecord.get("te*t"); node.parentId=(String)dataRecord.get("parentId"); nodeList.put(node.id,node); } //構(gòu)造無序的多叉樹 SetentrySet=nodeList.entrySet(); for(Iteratorit=entrySet.iterator();it.hasNe*t();){ Nodenode=(Node)((Map.Entry)it.ne*t()).getValue(); if(node.parentId==null||node.parentId.equals(")){ root=node; }else{ ((Node)nodeList.get(node.parentId)).addChild(node); } } //輸出無序的樹形菜單的JSON字符串 System.out.println(root.toString()); //對多叉樹進展橫向排序 root.sortChildren(); //輸出有序的樹形菜單的JSON字符串 System.out.println(root.toString()); //程序輸出結(jié)果如下〔無序的樹形菜單〕〔格式化后的結(jié)果〕: // { // id:'100000', // te*t:'**銀行總行', // children:[ // { // id:'110000', // te*t:'**分行', // children:[ // { // id:'113000', // te*t:'**銀行開發(fā)區(qū)支行', // leaf:true // }, // { // id:'111000', // te*t:'**銀行金光道支行', // leaf:true // }, // { // id:'112000', // te*t:'**銀行解放道支行', // children:[ // { // id:'112200', // te*t:'**銀行三大街支行', // leaf:true // }, // { // id:'112100', // te*t:'**銀行廣陽道支行', // leaf:true // } // ] // } // ] // } // ] // } //程序輸出結(jié)果如下〔有序的樹形菜單〕〔格式化后的結(jié)果〕: // {// id:'100000', // te*t:'**銀行總行', // children:[ // { // id:'110000', // te*t:'**分行', // children:[ // { // id:'111000', // te*t:'**銀行金光道支行', // leaf:true // }, // { // id:'112000', // te*t:'**銀行解放道支行', // children:[ // { // id:'112100', // te*t:'**銀行廣陽道支行', // leaf:true // }, // { // id:'112200', // te*t:'**銀行三大街支行', // leaf:true // } // ] // }, // { // id:'113000', // te*t:'**銀行開發(fā)區(qū)支行', // leaf:true // } // ] // } // ] // } }}/***節(jié)點類*/classNode{ /** *節(jié)點編號 */ publicStringid; /** *節(jié)點內(nèi)容 */ publicStringte*t; /** *父節(jié)點編號 */ publicStringparentId; /** *孩子節(jié)點列表 */ privateChildrenchildren=newChildren(); //先序遍歷,拼接JSON字符串 publicStringtoString(){ Stringresult="{" +"id:'"+id+"'" +",te*t:'"+te*t+"'"; if(children!=null&&children.getSize()!=0){ result+=",children:"+children.toString(); }else{ result+=",leaf:true"; } returnresult+"}"; } //兄弟節(jié)點橫向排序 publicvoidsortChildren(){ if(children!=null&&children.getSize()!=0){ children.sortChildren(); } } //添加孩子節(jié)點 publicvoidaddChild(Nodenode){ this.children.addChild(node); }}/***孩子列表類*/classChildren{ privateListlist=newArrayList(); publicintgetSize(){ returnlist.size(); } publicvoidaddChild(Nodenode){ list.add(node); } //拼接孩子節(jié)點的JSON字符串 publicStringtoString(){ Stringresult="["; for(Iteratorit=list.iterator();it.hasNe*t();){ result+=((Node)it.ne*t()).toString(); result+=","; } result=result.substring(0,result.length()-1); result+="]"; returnresult; } //孩子節(jié)點排序 publicvoidsortChildren(){ //對本層節(jié)點進展排序 //可根據(jù)不同的排序?qū)傩裕瑐魅氩煌谋容^器,這里傳入ID比較器 Collections.sort(list,newNodeIDparator()); //對每個節(jié)點的下一層節(jié)點進展排序 for(Iteratorit=list.iterator();it.hasNe*t();){ ((Node)it.ne*t()).sortChildren(); } }}/***節(jié)點比較器*/classNodeIDparatorimplementsparator{ //按照節(jié)點編號比較 publicintpare(Objecto1,Objecto2){intj1=Integer.parseInt(((Node)o1).id); intj2=Integer.parseInt(((Node)o2).id);return(j1<j2?-1:(j1==j2?0:1)); } }/***構(gòu)造虛擬的層次數(shù)據(jù)*/classVirtualDataGenerator{ //構(gòu)造無序的結(jié)果集列表,實際應用中,該數(shù)據(jù)應該從數(shù)據(jù)庫中查詢獲得; publicstaticListgetVirtualResult(){ ListdataList=newArrayList(); HashMapdataRecord1=newHashMap(); dataRecord1.put("id","112000"); dataRecord1.put("te*t","**銀行解放道支行"); dataRecord1.put("parentId","110000"); HashMapdataRecord2=newHashMap(); dataRecord2.put("id","112200"); dataRecord2.put("te*t","**銀行三大街支行"); dataRecord2.put("parentId","112000"); HashMapdataRecord3=newHashMap(); dataRecord3.put("id","112100"); dataRecord3.put("te*t","**銀行廣陽道支行"); dataRecord3.put("parentId","112000"); HashMapdataRecord4=newHashMap(); dataRecord4.put("id","113000"); dataRecord4.put("te*t","**銀行開發(fā)區(qū)支行"); dataRecord4.put("parentId","110000"); HashMapdataRecord5=newHashMap(); dataRecord5.put("id","100000"); dataRecord5.put("te*t","**銀行總行"); dataRecord5.put("parentId","); HashMapdataRecord6=newHashMap(); dataRecord6.put("id","110000"); dataRecord6.put("te*t","**分行"); dataRecord6.put("parentId","100000"); HashMapdataRecord7=newHashMap(); dataRecord7.put("id","111000"); dataRecord7.put("te*t","**銀行金光道支行"); dataRecord7.put("parentId","110000"); dataList.add(dataRecord1); dataList.add(dataRecord2); dataList.add(dataRecord3); dataList.add(dataRecord4); dataList.add(dataRecord5); dataList.add(dataRecord6); dataList.add(dataRecord7); returndataList; } }好了,通過上面的代碼,就可以實現(xiàn)多叉樹的兄弟節(jié)點橫向排序和先序遍歷了,實現(xiàn)了將層次數(shù)據(jù)轉(zhuǎn)換為有序無限級樹形構(gòu)造JSON字符串的目的。在實際的工程中,可以把上面的有效代碼融入其中,或者在此根底上進展一些擴展:實現(xiàn)對指定層次的排序〔例如只排序第一層的節(jié)點,或者只排序*一父節(jié)點下的所有子節(jié)點〕遍歷輸出樹形構(gòu)造時可以參加判斷條件過濾掉*些節(jié)點實現(xiàn)節(jié)點的刪除功能在節(jié)點類中增加一個父節(jié)點的引用,就可以計算出*一節(jié)點所處的級別在不支持層次查詢〔hieraricalretrival〕的數(shù)據(jù)庫應用系統(tǒng)中使用該算法實現(xiàn)一樣的效果四、思考與總結(jié)這篇文章的重點是如何構(gòu)造有序的無限級的樹形構(gòu)造JSON字符串,一次性生成樹形菜單,而不是利用AJA*的方式,反復向效勞器端發(fā)送請求,一級接一級的加載樹節(jié)點。既然可以構(gòu)造無限級的JSON字符串,則也可以根據(jù)這個思路構(gòu)造無限級的*ML字符串,或者構(gòu)造具有層次構(gòu)造的UL–LI組合〔用UL-LI來展示樹形構(gòu)造〕,或者構(gòu)造具有層次構(gòu)造的TABLE〔用TABLE來展示樹形構(gòu)造〕。如下所示:〔1〕*ML層次構(gòu)造<menuGroupid="100000"name="**銀行總行"> <menuGroupid="110000"name="**分行"> <menuid="113000"name="**銀行開發(fā)區(qū)支行"> </menu> <menuid="111000"name="**銀行金光道支行"> </menu> <menuGroupid="112000"name="**銀行解放道支行"> <menuid="112200"name="**銀行三大街支行"> </menu> <menuid="112100"name="**銀行廣陽道支行"> </menu> </menuGroup> </menuGroup></menuGroup>〔2〕UL-LI層次構(gòu)造<ul> <li>**銀行總行</li> <ul> <li>**分行<

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論