日期:2014-05-16 浏览次数:20355 次
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}});
?
效果图: