轉(zhuǎn)載:解析Tree2
在我的 blog 中,JSF 的Tree2 組件一直都是一個(gè)熱門的討論話題,為了向大家介紹更多關(guān)于Tree2的內(nèi)容,我翻譯了這篇原產(chǎn)于 Apache Myfaces 社區(qū)的介紹 Tree2 的文章,希望大家能夠?qū)?/font> Tree2 有更深的認(rèn)識(shí)。
在最后會(huì)附上一些我在使用中的體會(huì),和大家分享,如果大家有什么想法的話,可以和我多多交流了。本人第一次翻譯文章,難免會(huì)有很多不足之處,請(qǐng)大家諒解,也請(qǐng)多多指點(diǎn)。
英文原作:http://www.aygfsteel.com/steady/archive/2006/01/12/27814.html
轉(zhuǎn)載自:http://wiki.apache.org/myfaces/Tree2
正文如下:
Tree2組件使用HTML表格將你的數(shù)據(jù)呈現(xiàn)為一個(gè)樹。這個(gè)樹是動(dòng)態(tài)的:當(dāng)用戶點(diǎn)擊它們時(shí)它們可以展開或者折疊。該組件同時(shí)支持客戶端和服務(wù)端的交互方式,在客戶端交互時(shí)使用了JavaScript。在隨后的例子中,每次用戶的點(diǎn)擊將產(chǎn)生一個(gè)Request / Response 周期,并在新的視圖狀態(tài)(View State)中重新呈現(xiàn)新的樹結(jié)構(gòu)。
注:在后面的例子中只有可見的(已經(jīng)展開的節(jié)點(diǎn))數(shù)據(jù)被傳送到客戶端。而在第一個(gè)例子(客戶端Tree),在每個(gè)HTML Response中,整個(gè)樹都被發(fā)送到客戶端瀏覽器。樹的每個(gè)節(jié)點(diǎn)都包含了不少的HTML代碼(假定每個(gè)節(jié)點(diǎn)200個(gè)字符,這個(gè)大小將取決于你希望在節(jié)點(diǎn)上顯示的信息的量),這些信息將被傳送到瀏覽器,其中包括了那些不可見的節(jié)點(diǎn)(沒有展開的節(jié)點(diǎn)),因?yàn)樗鼈兊囊粋€(gè)祖系節(jié)點(diǎn)被展開。如果你有一個(gè)深度有四層的樹,平均每個(gè)結(jié)點(diǎn)擁有四個(gè)子結(jié)點(diǎn),這時(shí)候你就需要傳輸10 + 102 + 103 + 104 = 11 110個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)有200個(gè)字符,這個(gè)樹總共就有2 222 000個(gè)字符,也就是2M的數(shù)據(jù)。這個(gè)例子將向用戶說(shuō)明,雖然純客戶端Tree會(huì)給客戶端帶來(lái)更好的用戶體驗(yàn),但隨之而來(lái)的帶寬問題迅速的增長(zhǎng)。純客戶端的樹適用于小型的樹,或者在Intranet及寬帶連接中使用的中型大小的樹。對(duì)于大型的樹,或者你需要照顧到一些低帶寬的用戶的需要時(shí),你就需要使用服務(wù)端樹。你可以通過(guò)<t:tree2>的clientSideToggle這個(gè)屬性來(lái)選擇你使用的是客戶端的樹或者服務(wù)端的樹,<t:tree2 clientSideToggle="false" ...將會(huì)使用服務(wù)端的樹,屬性值設(shè)為true將會(huì)使用客戶端的樹,默認(rèn)值為true。
用法:
Backing Bean:
Tree2組件對(duì)Backing Bean中的一個(gè)TreeModel進(jìn)行操作。通常情況,你只要把這個(gè)TreeModel綁定到這個(gè)組件上就可以了,就像這樣:


下面需要建立一個(gè)類MyHandler,在faces-config.xml中的managed bean配置成myHandler,在例子中這個(gè)類提供了一個(gè)方法getTreeModel()用于返回一個(gè)TreeModel用于表示你的數(shù)據(jù)。






TreeModel實(shí)際上是對(duì)TreeNode實(shí)例進(jìn)行了一些簡(jiǎn)單的包裝。
TreeNode是一個(gè)接口,其中和tree2相關(guān)有四個(gè)方法:
String getType()
boolean isLeaf()
List getChildren()
int getChildCount()
其它方法都沒有什么用處了,可能會(huì)在今后的版本中取消。它們要求開發(fā)者在開發(fā)backing bean中做一些并不必要的操作。
int getChildCount() 方法返回這個(gè)節(jié)點(diǎn)的子結(jié)點(diǎn)數(shù)量,這個(gè)方法了很容易的采用如下的方式實(shí)現(xiàn):



該方法的出現(xiàn)使得對(duì)于子結(jié)點(diǎn)的延遲加載變的可行。該方法的實(shí)現(xiàn)只需要返回該節(jié)點(diǎn)的子結(jié)點(diǎn)數(shù)量,而不需要返回每個(gè)子結(jié)點(diǎn)的實(shí)例。
boolean isLeaf() 方法在該節(jié)點(diǎn)沒有子節(jié)點(diǎn)的時(shí)候返回true。這樣,一個(gè)很直截了當(dāng)?shù)膶?shí)現(xiàn)可以這樣:



不管你提供了什么樣的實(shí)現(xiàn),在任何時(shí)間任何情況下你都得保持getChildren().isEmpty() ==> isLeaf()。isLeaf()方法實(shí)際上控制了節(jié)點(diǎn)被怎樣呈現(xiàn):是否被當(dāng)做樹葉節(jié)點(diǎn)(不能被繼續(xù)展開)。
String getType() 方法決定了用怎樣的方式來(lái)呈現(xiàn)這個(gè)節(jié)點(diǎn)。在 JSF 頁(yè)面中,可以在 <t:tree2> 的Tag 中嵌套facet,JSF將會(huì)選出與 getType() 方法返回值同名的 facet 用于呈現(xiàn)。如果該節(jié)點(diǎn)沒有找到相符的 facet,將會(huì)導(dǎo)致一個(gè)錯(cuò)誤,并且這個(gè)方法不會(huì)返回null。
List getChildren() 方法返回一個(gè) List,其中包含了該節(jié)點(diǎn)下所有的 TreeNode,這就表示這些節(jié)點(diǎn)將被呈現(xiàn)為該節(jié)點(diǎn)下的子結(jié)點(diǎn)。該 List 不能包含 null,如果該 List 的大小和getChildCount()不符,將會(huì)報(bào)錯(cuò)。子結(jié)點(diǎn)將按照它們?cè)?span lang="EN"> List 中的順序呈現(xiàn)出來(lái)。
改變Tree中的內(nèi)容
(當(dāng)展開樹的節(jié)點(diǎn)時(shí),在后臺(tái)延遲加載)
在郵件列表中有很多關(guān)于這項(xiàng)任務(wù)的問題和討論,我(Marcel,一個(gè) JSF 的初學(xué)者)在這里總結(jié)一下。如果你有更好的解決方案,請(qǐng)更新這些文字。
在這里存在的一個(gè)問題就是我要這樣把“+”圖標(biāo)去掉:
· <t:tree2 ... showNav="false" ...>
然后再讓文件夾圖標(biāo)(代表包含子節(jié)點(diǎn)的節(jié)點(diǎn))變的可點(diǎn)擊:
· <h:commandLink action="#{t.toggleExpanded}" actionListener="#{navigationBacker.processAction}">
然后在 Java 代碼中接受鼠標(biāo)點(diǎn)擊的事件。在 NavigationBacker.java 文件中的processAction(ActionEvent e) 方法里,我從 EJB3-persistency 中加載子結(jié)點(diǎn)的數(shù)據(jù)。
不好的是“+”圖標(biāo)變的不可見,但是我現(xiàn)在沒有辦法獲取點(diǎn)擊“+”圖標(biāo)的事件。
看起來(lái)在org.apache.myfaces.custom.tree2.HtmlTree.java這個(gè)文件里是通過(guò)注冊(cè)了_expandControl = new HtmlCommandLink(); 從內(nèi)部獲取“+”的點(diǎn)擊事件,但是我現(xiàn)在沒有辦法從我的代碼中接受到這一事件。
為了導(dǎo)航,我使用了含有entries的TreeNode.getIdentifier() (參見:#{node.identifier}),看起來(lái)就是這個(gè)樣子:
· db_id="car_id=7,person_id=2"
這代表了后臺(tái)數(shù)據(jù)庫(kù)表的主鍵(我還沒有找到一個(gè)更好的解決方案用于導(dǎo)航)
程序代碼如下:
navigation.jsp


























NavigationBacker.java












































這里有一段輔助代碼用于從 h:commandLink 中獲取 f:param 用于多種用途。


























注:在上面的例子里,backing bean都存放于 session 作用域里,可以在WEB-INF/examples-config.xml 中進(jìn)行配置。
很多朋友和我交流了一些有關(guān) Tree2 的問題,我把一些大家經(jīng)常碰到的問題拿出來(lái),希望剛開始學(xué)習(xí)的朋友能夠避免再犯一些這樣的錯(cuò)誤。
1.首先就是關(guān)于 myfaces 包的問題,Myfaces 1.1.1 release 版本的 Tree2 是有 bug 的,大概在十一月份的時(shí)候修正了大部分問題,但是由于這以后并沒有 release 版本出來(lái),所以大家可以使用一些較新一點(diǎn)的 Nightly Build,可以去這里找找http://cvs.apache.org/builds/myfaces/nightly/ ,不過(guò)從元旦后似乎改用了 Maven 后還沒有一個(gè) Build 出來(lái),我手上有一個(gè)12.30 Build的版本,如果需要的話可以和我聯(lián)系。因?yàn)檫@些 Nightly Build 不確定可能還會(huì)有其它的一些問題,所以用的時(shí)候要慎重一點(diǎn)。
2. 有些朋友就直接把代碼貼上去用,會(huì)碰到一些諸如點(diǎn)擊沒有反應(yīng)或者圖標(biāo)顯示不出來(lái)的問題,很多時(shí)候是因?yàn)闆]有加上MyFaces' Extensions Filter,相關(guān)的內(nèi)容可以參考我前面寫的http://www.aygfsteel.com/steady/archive/2005/11/17/20170.html。
posted on 2006-01-14 03:40 Vincent.Chen 閱讀(353) 評(píng)論(0) 編輯 收藏 所屬分類: Java