***************************************
關鍵字:AJAX,Tree,Struts,DOM
難易度: 中
軟件版本:struts 1.2.8
時間:2006-01-27
Author:Kino
***************************************
前陣子寫了一個小代碼處理AJAX下WebTree的構建,其中碰到了一些問題,也有一些想法,現在說出來希望大家一起看看,如果案由問題請不吝賜教,本人不勝感激啊。
背景:
這次因為是加載在Struts上的開發,Web頁面上的Tree作AJAX處理,因為有Node的增刪改操作。Server端因為要和WebService連接,所以不做Cache。
解決案:
1。使用Polling調用AJAX定期更新Tree。
2。AJAX訪問的地址是一個Action(例:createtree.do)。用來返回Tree模型或者錯誤消息(國際化)。
3。Browser解析XML的TreeModel。
4。在Browser比較新舊2個TreeModel,完成選中狀態的繼承。
5。CSS渲染TreeNode。
以上是簡單的思路。傳統的AJAX應該是盡量減少XMl傳輸量,迫于沒有Cache的緣故,并且WS給我的節點并不能簡單的得到父子關系。我選擇了,每次Polling更新整棵樹的方案。性能未測。
我這次在web server 端構建Tree時直接用深度優先轉換成XML。XMl中數據的先后順序決定了Tree從父到子,從兄到弟的深度優先關系,indent決定了深度(也就是縮進)。這樣我從Server端傳入的也就成了一個標準的Tree顯示Model。格式定義如下。
* Gobal Master Tree DTD
* <!ELEMENT tree (tree*)>
* <!ATTLIST tree
* id CDATA #REQUIRED LoctionInfo's toString
* indent CDATA #REQUIRED Tree's Level
* text CDATA #REQUIRED label in html
* tooltip CDATA #IMPLIED title in html
* action CDATA #IMPLIED href in html
* icon CDATA #IMPLIED close icon with the node status
* openicon CDATA #IMPLIED open icon with the node status
* open CDATA #IMPLIED> node's open states ,default is false in server.
* target CDATA #IMPLIED node's open target
*
<span id="maintree">
<tree id="Ajax" indent=0 text="Root" tooltip="Root" action="/logout.do" icon="" openicon= "" open="false"/>
<tree id="110" indent=1 text="Node 1" tooltip="Node 1" action="/logout.do" icon="" openicon= "" open="false"/>
<tree id="120" indent=2 text="Node 2" tooltip="Node 2" action="/logout.do" icon="" openicon= "" open="false"/>
<tree id="12580" indent=2 text="Node 3" tooltip="Node 3" action="/logout.do" icon="" openicon= "" open="false"/>
<tree id="user" indent=1 text="Node 4" tooltip="Node 4" action="/logout.do" icon="" openicon= "" open="false"/>
</span>
上邊的 Tree顯示出來如下
Root
│
├Node 1
│ │
│ ├Node 2
│ └Node 3
└Node 4
indent 就是縮進。
數據的先后順序就是深度優先的遍歷順序。
這樣的數據到了Browser,會先被轉成一個對象數組。

2

3

4

5

6

7

8

9

10

11

12



13

14

15

16

17

18

19

20

21

22

23

24

25

然后會和正在顯示的Tree數組 進行一個 比較,用于寫入展開狀態,代碼如下:

2

3

4

5

6



7

8



9

10

11

12

13



14

15

16

17

18

19

20

21



22

23



24

25



26

27

28

29

30

31

32

33

34

轉換Html部分算是一個比較容易出bug的危險點。
首先分析一下,生成的代碼是什么樣子的。
這里仍然用上邊的那棵樹作例子。
生成的DOM結構應該是
<div 父>
<div 收縮>
<img 折線 />
<img 圖標 />
<a 節點動作>節點Label</a>
<div 子>
....遞歸的構造
</div 子>
</div 收縮>
</div 父>
其次 對于這種并不直接含有父子關系的節點首先要判明一個節點的子 和 兄弟,然后用遞歸解決。
遞歸的思路如下深度優先:
function toHtml(節點index)
{
var child_html;
if 這個節點有子
{
Loop子節點
{
child_html[i] = toHtml(子節點index);
i++;訪問下一個子節點
}
var 所有子節點Html模塊 = <div 收縮> child_html.join("") </div>
var 本節點Html模塊 = <div 本節點><div 收縮><img ><img 圖標 /><a 節點動作>節點Label</a>所有子節點Html模塊</div 收縮></div 本節點>;
return 本節點Html模塊;
}
樹就構建好了。
作為顯示,使用了CSS的
background-repeat: repeat-y;
background-image: url("../images/tree/I.png") !important;
background-position-y: 1px !important; /* IE only */
還有padding-left作Div的向右偏移,默認的偏移量是19個像素點,然后根據Tree顯示模型的indent相乘就ok了。
思路就是這些。希望能對 朋友們有所幫助。
歡迎討論。