首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

JSF Tree2 組件深度解析:客戶端與服務端交互模式選型指南

     編輯:Java 程式設計入門

Tree2 組件架構概覽

<t:tree2> 以 HTML 表格渲染樹狀結構,支持動態展開/折疊。其核心特性在於雙模式交互:

  • 客戶端模式(clientSideToggle="true",預設):整棵樹一次性渲染至瀏覽器,JavaScript 處理展開/折疊,無網絡往返,體驗流暢。
  • 服務端模式(clientSideToggle="false"):每次點擊觸發 Request/Response 週期,僅傳輸可見節點,適合大數據量或低帶寬場景。

帶寬權衡:為什麼大樹必須用服務端模式

假設:深度 4 層、平均分支 4、每節點 200 字符 HTML。
客戶端模式總傳輸量 ≈ 1 + 4 + 16 + 64 = 85 個節點 × 200 字符 = 17 KB(僅示例)。
實際生產環境中,節點包含圖標、鏈接、樣式、隱藏字段,單節點常超過 1 KB。百萬級節點樹將產生數百 MB HTML,導致:

  • 首屏加載極慢
  • 瀏覽器渲染/內存壓力大
  • 移動端/弱網絕不可用

決策原則:節點總數 < 500 且內網環境 → 客戶端模式;否則強制服務端模式。

Backing Bean 與 TreeModel 契約

組件綁定 #{myHandler.treeModel},TreeModel 封裝根 TreeNode。TreeNode 接口四大核心方法:

方法職責實現要點
getType()返回節點類型標識,決定使用哪個 <f:facet> 渲染不可返回 null;無匹配 facet 拋異常
isLeaf()判斷是否葉子節點(不可展開)必須與 getChildren().isEmpty() 一致
getChildCount()返回子節點數量,支持延遲加載僅計數,不實例化子節點,關鍵優化點
getChildren()返回子節點 List,順序即渲染順序不含 null;size() 必須等於 getChildCount()

延遲加載實戰:按需查詢子節點

public class LazyTreeNode implements TreeNode {
    private String id;
    private List<TreeNode> children; // null 表示未加載

    public int getChildCount() {
        return childCountFromDB(id); // 僅查 count(*)
    }

    public List<TreeNode> getChildren() {
        if (children == null) {
            children = loadChildrenFromDB(id); // 真正加載
        }
        return children;
    }
    // isLeaf()、getType()...
}

配合 clientSideToggle="false",用戶點擊「+」時才觸發查詢,極大降低首屏負載。

自定義節點渲染:Facet 機制

<t:tree2 value="#{handler.treeModel}" var="node" clientSideToggle="false">
  <f:facet name="folder">
    <h:commandLink action="#{node.toggleExpanded}">
      <h:graphicImage value="/icons/folder.png" />
      <h:outputText value="#{node.name}" />
    </h:commandLink>
  </f:facet>
  <f:facet name="document">
    <h:outputText value="#{node.name}" styleClass="leaf-node" />
  </f:facet>
</t:tree2>

getType() 返回 "folder" 或 "document",JSF 自動選擇對應 Facet。可為不同業務類型定義專屬渲染邏輯(如權限圖標、拖拽控制柄)。

隱藏導航圖標,改用資料夾圖標觸發展開

<t:tree2 ... showNav="false">
  <f:facet name="folder">
    <h:commandLink action="#{tree.toggleExpanded}" 
                   actionListener="#{navigationBacker.processAction}">
      <h:graphicImage value="/icons/folder_open.png" />
      <h:outputText value="#{node.name}" />
    </h:commandLink>
  </f:facet>
</t:tree2>

showNav="false" 移除默認「+/-」圖標,commandLink 綁定 tree.toggleExpanded 實現點擊資料夾展開,actionListener 可記錄展開狀態或執行權限檢查。

最佳實踐清單

  1. 默認啟用服務端模式,僅在極小樹且內網環境下開啟客戶端模式。
  2. 必須實現 getChildCount() 延遲計數,避免預加載海量子節點。
  3. 節點類型盡量細分(folder/document/leaf/locked 等),配合 Facet 實現差異化 UI。
  4. 大樹啟用分頁/虛擬滾動:自定義 getChildren() 返回可分頁的 List 包裝類。
  5. 狀態保存:展開路徑存入 Session/ViewState,頁面刷新後恢復用戶上下文。

總結

JSF Tree2 通過模式切換與延遲加載契約,優雅解決了樹狀組件的性能與體驗難題。關鍵在於:誠實評估數據規模,果斷選擇服務端模式,並徹底落實 getChildCount()/getChildren() 分離加載。配合 Facet 機制,可構建出企業級的權限樹、組織架構樹、文件瀏覽器等複雜場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved