日期:2014-05-16  浏览次数:20367 次

ExtJS 4.1 下 TreePanel 的异步(分次)数据请求

前阵子用 ExtJS  4.1 + IIS + ASP 做了一个在线文档的小工具,功能大致上是这样的,把服务端做为文档服务器,然后将存放文档的目录发布为一个站点,用 ExtJS实现一个类似资源管理器模式的访问页面,页面的左侧是文件夹导航栏,文件夹的结构与服务器上的一致。对于已知的文件格式,直接在服务端生成 PDF 文件后返回给浏览器端,就这样只需要浏览器就可以在线阅读文档。

起初该工具运行的很好,但随着文档数目的增加,文件夹的层级加深,一些问题就显现了,原先的设计是采用 FileSystemObject 将文档目录进行了一个递归遍历,把遍历结果组织成 Json 文件返回给浏览器,在文档数目不大,文件夹层级不深的情况下,是可以工作的很好的,反正是在公司内网使用 :),现在文档数目增加了,就不得不考虑优化的工作了,于是决定改写一下,让  TreePanel 支持异步的数据请求。

在网上查了很多资料,不少的范例都是介绍使用 asyncTreeNode、TreeLoader 来实现异步数据请求,最后还是上官网论坛看到一帖子,明确的指出 TreePanel 已经不再使用 TreeNodes 来实现异步数据请求了,具体什么版本开始不知道,帖子的发布时间是2011年3月份的,所以我认为在 ExtJS 4 这个版本上肯定是不支持了,以下是原文地址:

点击打开链接



在上述的链接中,还留意到其实在4.x版本下的 store 已经是按异步模式进行优化的,除非你在返回的数据中定义了 children ,否则当 TreePanel 和 store 配合使用时,在展开树节点时 store 是会自动引发请求来更新展开节点的数据的,几乎不用写什么代码就可以实现开篇时所提出的需求。原文如下:



 于是去找开发包自带的范例,找到  examples\tree\ 下的 reorder.html,reorder.js,reorder.js的代码如下:

Ext.require([
    'Ext.tree.*',
    'Ext.data.*',
    'Ext.tip.*'
]);

Ext.onReady(function() {
    Ext.QuickTips.init();
    
    var store = Ext.create('Ext.data.TreeStore', {
        proxy: {
            type: 'ajax',
            url: 'get-nodes.php'
        },
        root: {
            text: 'Ext JS',
            id: 'docs',
            expanded: true
        },
        folderSort: true,
        sorters: [{
            property: 'text',
            direction: 'ASC'
        }]
    });

    var tree = Ext.create('Ext.tree.Panel', {
        store: store,
        renderTo: 'tree-div',
        height: 300,
        width: 250,
        title: 'Files',
        useArrows: true
    });
});

我跟踪了这个代码的执行,当首次打开 reorder.html 这个页面时,会引发一次对 get-nodes.php 的请求,此时的请求链接 大致上是这样的:

..../get-nodes.php?_dc=8761836491987632467&node=docs&............

这里着重要说明的是node参数,这个参数就是在定义 store 对象时指定的 id 值,请留意上面的代码,在 root : {} 的定义里,这个参数的实际意义是告诉 get-nodes.php 以 docs 这个位置开始做为根节点开始构建 TreePanel 所需要的树,仅需返回当前层的数据,以文件系统的目录结构为例,假如 docs下的目录结构如下:


收到请求后,get-nodes.php 接收到 node参数指向 docs,于是返回docs下的文件夹和文件,但不会继续往下进行递归遍历,因此返回的数据有两种节点,一种是叶子节点,代表文件,一种是非叶子节点,代表文件夹,请留意文件夹节点并没有 children 项。Json数据大概是以下这个样子:

{text: '.',children:[
    {id:'docs/dealers',text:'dealers',expanded:false},  // 文件夹节点
    {id:'docs/Test2',text:'Test2',expanded:false},
    {id:'docs/知识库',text:'知识库',expanded:false},
    {text:'ShowIIS.asp',leaf:true},
    {text:'startPage.png',leaf:true}
]}

值得留意的是,文件夹节点的 id 值的设置,这是一种约定,在每个文件夹节点中用 id 来定义该文件夹的寻址路径,这样当用户在 TreePanel 单节这个文件夹节点时,stroe 对象将会以这个 id 值做为参数再次向服务端发起请求,例如:用户单击节点 “知识库” ,引发的请求的链接会是以下这个样子:

..../get-nodes.php?_dc=9384750928743059&node=docs/知识库&............

因为在上一次请求返回 “知识库” 这个节点信息时 get-nodes.php 的处理代码定义了其 id 值为 docs/知识库,所以单击 知识库 这个节点 store 会以该节点的 id 值做为参数引发新的请求,这正是 store 实现分次请求的核心机制。

当请求的数据回来后 TreePanel 会自动将数据添加到被点击的节点之下,以此类推,返回 知识库下 编程技术 文件夹节点的 id 值就是:docs/知识库/编程技术,基于这个机制,TreePanel也就实现了按展开的节点来分次请求数据。

想看完整的例子,可以找开发包自带的,位置在:examples\tree\ 下的 reorder.html,reader.js,get-nodes.php