ExtJS树面板TreePanel使用实例解析

作者:技术拾光时间:2026-06-11 08:29:01浏览:251

在 Ext JS 树组件中,无论是叶子节点还是非叶子节点,都使用同一个 TreeNode 类来表示,这种设计保持了高度统一。但在具体节点类型上,分为两种:普通简单树节点由 Ext.tree.TreeNode 定义,支持异步加载子节点的节点由 Ext.tree.AsyncTreeNode 定义。换言之

在 Ext JS 树组件中,无论是叶子节点还是非叶子节点,都使用同一个 TreeNode 类来表示,这种设计保持了高度统一。但在具体节点类型上,分为两种:普通简单树节点由 Ext.tree.TreeNode 定义,支持异步加载子节点的节点由 Ext.tree.AsyncTreeNode 定义。换言之,当数据量较小、结构固定时,使用前者;若需要按需从服务器获取数据,则需使用后者。

在数据层面,关键字段包括:text 用于显示节点文字,leaf 标记是否为叶子节点,children 存放子节点数组,expanded 控制初始展开状态。典型的数据结构示例如下:

var store = Ext.create('Ext.data.TreeStore', {
    root: {
        expanded: true,
        children: [
            { text: "留学", leaf: true },
            { text: "功课", expanded: true, children: [
                { text: "英语", leaf: true },
                { text: "代数", leaf: true }
            ] },
            { text: "托福", leaf: true }
        ]
    }
});

TreePanel 从 Servlet 中读取 JSON 数据

实际项目中,树的数据很少直接写在页面中,通常需要从服务器动态获取。以下演示通过返回 JSON 的 Servlet 实现前台 TreePanel 通过 loader 访问数据。

服务端代码是一个简单的 TreeNodeServlet,根据请求参数 node 返回不同的 JSON 片段:

import ja va.io.IOException;
import ja va.io.PrintWriter;
import ja vax.servlet.http.HttpServletRequest;
import ja vax.servlet.http.HttpServletResponse;
import ja vax.servlet.ServletException;
import ja vax.servlet.http.HttpServlet;

public class TreeNodeServlet extends HttpServlet {
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        String treeNode = request.getParameter("node");
        String json = "";
        PrintWriter out = response.getWriter();
        if ("0".equals(treeNode)) {
            json += "[{id:1, text:'0-1'}, {id:2, text:'0-2'}]";
        } else if ("1".equals(treeNode)) {
            json += "[{id:11, text:'0-1-1', leaf:true}, {id:12, text:'0-1-2', leaf:true}]";
        } else if ("2".equals(treeNode)) {
            json += "[{id:21, text:'0-2-1'}, {id:22, text:'0-2-2', leaf:true}]";
        } else if ("21".equals(treeNode)) {
            json += "[{id:211, text:'0-2-1-1', leaf:true}, {id:212, text:'0-2-1-2', leaf:true}]";
        }
        out.write(json);
    }
}

前台代码则较为简洁:创建 TreePanel,指定 loader 的 dataUrl 指向上述 Servlet,并设置根节点(需使用 AsyncTreeNode,因为数据采用懒加载),最后调用 root.expand() 触发首次加载。

Ext.onReady(function() {
    var tree = new Ext.tree.TreePanel({
        el: 'div-tree',
        loader: new Ext.tree.TreeLoader({ dataUrl: '../TreeNodeServlet' })
    });
    var root = new Ext.tree.AsyncTreeNode({ id: '0', text: '0' });
    tree.setRootNode(root);
    tree.render();
    root.expand();
});

运行效果截图:

ExtJS树面板TreePanel使用实例解析

在树 TreePanel 之间拖放节点

有时需要将一棵树的节点拖放到另一棵树中。同一棵树内拖动时,设置 enableDD: true 即可;跨树拖动则需分别设置 enableDrag 和 enableDrop。以下是一个完整示例。

1. JS 代码

Ext.onReady(function() {
    var tree1 = new Ext.tree.TreePanel({
        el: 'tree1',
        enableDrag: true,   // 允许从此树拖出
        loader: new Ext.tree.TreeLoader({ dataUrl: 'treeData1.txt' })
    });
    var tree2 = new Ext.tree.TreePanel({
        el: 'tree2',
        enableDrop: true,   // 允许将元素拖入此树
        loader: new Ext.tree.TreeLoader({ dataUrl: 'treeData2.txt' })
    });
    var root1 = new Ext.tree.AsyncTreeNode({ text: '根节点' });
    var root2 = new Ext.tree.AsyncTreeNode({ text: '图书' });
    tree1.setRootNode(root1);
    tree2.setRootNode(root2);
    tree1.render();
    tree2.render();
});

2. HTML 代码

3. 数据文件(JSON 格式)

treeData1.txt:

[
    { text: '非叶子结点' },
    { text: '叶子结点', leaf: true }
]

treeData2.txt:

[
    { text: '计算机', children: [
        { text: 'Ja va', children: [
            { text: 'Ja va核心技术', leaf: true },
            { text: 'Thinking in Ja va', leaf: true }
        ]},
        { text: '算法导论', leaf: true }
    ]},
    { text: '音乐', children: [
        { text: '乐理基础', leaf: true },
        { text: '卡尔卡西古典吉他教程', leaf: true }
    ]}
]

4. 运行效果

下图展示两个树之间的拖放交互:

ExtJS树面板TreePanel使用实例解析

以上是 Ext JS 树组件在数据加载与跨树拖放方面的典型用法。在实际项目中,可根据需求扩展节点数据、添加事件监听,甚至实现自定义拖放逻辑。需要牢记的是,AsyncTreeNode 是实现异步加载的核心,而 enableDrag/enableDrop 是跨树拖放的关键开关。