日期:2014-05-16 浏览次数:20426 次
Ext的Tree组件很好用,但是当节点多的时候,加载会很慢,如果能够带上分页的话,那就很好了,于是我想对Tree组件进行扩展,使之能够实现分页,这样就可以解决节点多的时候,页面加载速度的问题了
?
我的分页思路比较简单,就是对最顶层的根节点进行分页,也就是root节点,通过前台传过去的分页参数,在后台将数据按页读取出来,然后再前台的根节点下面展现出来,来实现分页的效果,至于后来的分页如何实现,就不在本文章的讨论范围内。本文章只讨论前台的展现。
?
实现思路:
由于Tree组件是通过TreePanel来展现的,而TreePanel有个bbar属性,可以放PagingToolbar对象,因此我们可以把分页组件树页面展现出来了,但是PagingToolbar的分页是需要通过Store来支持的,而我们的Tree组件是没有Store,只有loder,因此主要的着手点就在于构造一个可以让PagingToolbar分页时可以识别,并且能够自动调用loader获取节点的Store就可以,因为tree组件的laod方法,可以读取出节点,并展现成熟,因此只要store在load的时候,能够把节点load出来就可以,所以基本的做法就是在Store的load方法中调用tree组件的loader的load方法获取节点并展现,这是把需要分页的参数传到后来即可。思路是挺简单的,接下来看看实现的代码
?
/**
* 树分页数据源加载器,只对最顶层根节点进行分页,这意味着,子节点的节点数目不能太多,否则会有性能问题
* @class Ext.tree.TreeLoaderStore
* @extends Ext.data.Store
*/
Ext.tree.TreeLoaderStore = Ext.extend(Ext.data.Store,{
/**
* 加载数据源的数据对象,是树结构的loader
* @type Ext.tree.TreePagingLoader
*/
loader:null,
/**
* 树的根节点,最顶的节点
* @type Ext.tree.AsyncTreeNode
*/
rootNode:null,
constructor : function(config){
Ext.tree.TreeLoaderStore.superclass.constructor.call(this);
this.loader = config.loader;
this.rootNode = config.rootNode;
},
load:function(options){
var _self = this;
if(!this.loader || !this.rootNode){
Ext.MessageBox.alert("错误","必须指定loader或者rootNode");
return false;
}
Ext.apply(this.loader.baseParams,{start:options.params.start,limit:options.params.limit}),
this.loader.load(this.rootNode,function(node){
_self.currentCount = _self.loader.currentCount;
_self.totalLength = _self.loader.totalCount;
node.expand();
_self.fireEvent("load",_self,null,options);
delete _self;
});
return true;
},
getCount : function(){
return this.currentCount || 0;
},
getTotalCount : function(){
return this.totalLength || 0;
}
})
Ext.tree.TreePagingLoader = Ext.extend(Ext.tree.TreeLoader,{
processResponse : function(response, node, callback, scope){
var json = response.responseText;
try {
var o = response.responseData || Ext.decode(json);
//TODO:暂时从后台获取当前页的记录数,通过currentCount属性获取
//最佳做法是效仿pagingToolbar的做法,在客户端获取
//目前的障碍是,loader还没读取完,翻页的工具栏已经初始化了,导致当前页记录数无法获取
//有空再继续修改,思路是把loader当store来用
this.totalCount = o.totalCount;
this.currentCount = o.data.length;
var o = o.data;
node.beginUpdate();
for(var i = 0, len = o.length; i < len; i++){
var n = this.createNode(o[i]);
if(n){
node.appendChild(n);
}
}
node.endUpdate();
this.runCallback(callback, scope || node, [node]);
}catch(e){
this.handleFailure(response);
}
}
})
?
用法:
var root = new Ext.tree.AsyncTreeNode({
text: '数据字典',
expanded :false,
draggable:false,
id:"1" });
var loader = new Ext.tree.TreePagingLoader({
dataUrl:"cotmodule.do?method=querySysDic&&query=1" ,
listeners : {
'click' : function(loader,node) {
//alert(node.href);
this.baseParams.type = node.id;
}
}
}) ;
var store = new Ext.tree.TreeLoaderStore({
rootNode:root,
loader:loader
});
var bbar = new Ext.PagingToolbar({
pageSize: 15,
store: store,
displayInfo: true,
displayMsg: '显示第 {0} - {1}条记录 共{2}条记录',
displaySize:'5|10|15|20|all',
emptyMsg: "无记录"
});
var myTree = new Ext.tree.TreePanel({
region:"center",
autoScroll:true,
animate:true,
enableDD:true,
containerScroll: true,
bbar:bbar,
root:root,
loader:loader
});
store.load({params:{start:0,limit:15}});
?
效果图: