這幾天用到了Extjs的TreePanel來建立樹形菜單,在網上沒瞧見一個好的示例,遂決定寫一個,供後來者參考(本文下方的“附件下載下傳”可下載下傳本示例的完整源代碼)。
先建立一個雛形,代碼如下:
var tree = new Ext.tree.TreePanel({
title : '主菜單',
width : 200,
autoScroll : true,
singleExpand : true,
rootVisible : true,
animate : true,
//樹加載器
loader : new Ext.tree.TreeLoader({
dataUrl : 'tree/treeNodeAction_listTree.action'
})
});
(代碼1)
注意這裡使用了一個loader屬性,其值為一個Ext.tree.TreeLoader對象。根據它的名字,我們就能推測出這個對象是用來加載樹的,而其dataUrl屬性則指定應從何處加載樹的結點資訊。
緊接着建立根節點,并将此根結點設定為樹的根:
var root = new Ext.tree.AsyncTreeNode({
id : 'root',
text : '根',
expanded : true
});
//将此根結點設定為樹的根
tree.setRootNode(root);
(代碼2)
這裡注意以下幾點:
1、AsyncTreeNode是一種異步加載的結點,即每次隻加載本結點的直接子結點,而子結點的子結點(即目前結點的孫子結點)則在需要的時候再加載,這就提高了響應速度;
2、AsyncTreeNode也有loader屬性,它的值繼承自TreePanel中的loader屬性(見代碼1)。根結點使用此loader來加載它的子結點資訊并建立子結點,而子節點也是AsyncTreeNode對象,它們的loader屬性值也來自TreePanel的loader屬性,它們也将使用此loader來加載自己的子結點資訊,以此類推;
3、背景發送來的代表子結點資訊的JSON字元串必須以方括号“[]”包含,如本例加載根節點的子結點資訊的JSON字元串如下:
[{id:'module1',text:'子產品1',leaf:false},{id:'module2',text:'子產品2',leaf:true,url:'demo/module2.jsp'}]
(代碼3)
加載效果如下圖所示:
<a href="http://blog.51cto.com/attachment/201304/202955678.png" target="_blank"></a>
(圖1:主菜單截圖)
4、當加載結點的子結點時,會向背景傳送一個node參數,值為目前結點的id。如加載根節點的子節點時,會把根節點的id值&ldquo;root&rdquo;(見代碼2的根節點的id屬性)傳到背景,FireBug的截圖如下:
<a href="http://blog.51cto.com/attachment/201304/203058955.png" target="_blank"></a>
(圖2:node參數截圖)
這樣,背景就會從資料庫中讀取那些父結點的id為node值的結點資訊,即目前結點的子結點資訊。這樣,本示例的結點資訊在資料庫表中的形式就如下圖所示:
<a href="http://blog.51cto.com/attachment/201304/203218480.png" target="_blank"></a>
(圖3:表中的結點資訊)
注意觀察parent_id值為root的兩個結點,即為圖1主菜單截圖中的根結點的兩個子結點。
同理,背景向前台發送結點資訊時,也應該提供該結點的id值(參見代碼3的JSON字元串),供将來加載此結點的子結點時使用。
到目前為止,我們已經成功生成了樹,并可以動态加載其結點資訊。但我們最終的目标應該是點選TreePanel(一般放置于頁面的左邊)的某個葉子結點時,能在頁面右部顯示相關的功能頁面。為了實作這個功能,應該使用Viewport,其布局為border。然後将TreePanel放置于Viewport的西區,再建立一個TabPanel,放置于Viewport的中央區。為TreePanel添加click事件處理函數,在這個函數中,若相關的頁面沒有被加載,則建立一個Panel加載此頁面,并添加到TabPanel中,然後設定此Panel為活動的,顯示給使用者;若相關頁面已被加載,則直接設定其為活動的即可。具體代碼如下所示(注意:其中的center即為位于中央區的TabPanel):
listeners : {
click : function(node) {
// node代表被點選的結點,通過其attributes屬性讀取
// 背景傳來的url等屬性,url指該結點指向的頁面
var url = node.attributes.url;
var id = node.attributes.id;
// 從center中擷取相關的Panel
var tab = center.getItem('tab_' + id);
// 隻有當url存在,才進行後續處理
if (url) {
// 如果相關的Panel已存在,直接将其設定為活動的即可
if (tab) {
center.setActiveTab(tab);
} else {
// 否則建立一個Panel,用于加載url指向的頁面,然後
// 将此Panel添加到center中,并設定其為活動的
tab = new Ext.Panel({
title : node.attributes.text,
html : "<iframe src='"
+ url
+ "'"
+ " width='100%' height='100%' frameborder='0' scrolling='auto'>"
+ "</ifame>",
closable : true,
layout : 'fit',
frame : false,
id : 'tab_' + id
});
center.add(tab);
}
}
}
}
(代碼4)
需要注意的是,隻有葉子結點才有url屬性,這一點從代碼3的JSON字元串即可看出:id為module1的結點為非葉子結點,因而背景并沒有給它傳遞url資訊;而id為module2的結點為葉子結點,就有url屬性。
效果如圖所示(本示例的完整源代碼請于本文下方的&ldquo;附件下載下傳&rdquo;處下載下傳):
<a href="http://edu.51cto.com/course/course_id-1110.html" target="_blank">點選此處觀看作者的MyBatis 3從入門到提高視訊教程</a>
<a href="http://down.51cto.com/data/2362555" target="_blank">附件:http://down.51cto.com/data/2362555</a>
本文轉自 NashMaster2011 51CTO部落格,原文連結:http://blog.51cto.com/legend2011/1171733,如需轉載請自行聯系原作者