背景
一般情况下,分页展示是前端只负责展示,后台通过SQL语句实现分页查询。当总数据量在千条以下,适合一次性查询出符合条件的所有数据,让前端页面负责分页也是一种选择。
实例
现通过ExtJS 4扩展类库Ext.ux.data.PagingStore来实现分页,建议使用前在GitHub获取最新版本。
使用时非常简单,只需将Store的继承类改为“Ext.ux.data.PagingStore”,其他分页配置可参照之前的文章《ExtJS实现分页grid paging》。
Ext.define('XXX', {
extend : 'Ext.ux.data.PagingStore'
...
})
但是,针对不同的应用场景还有2个疑问:
-
本地分页后,如何强制重新查询后台数据?
根据PagingStore的实现来看,只有查询参数修改后才会再次调用后台进行查询。但是,如果我们修改了列表中某条数据后,需要按当前条件刷新列表。这时,我是在条件中添加一个时间戳来进行刷新的。
-
store.getProxy().extraParams._TIME=new Date().getTime();
-
分页按钮中的“刷新”如何去除?
因为是本地分页,ExtJS自带的分页“刷新”按钮似乎成了摆设。可以在页面加载完成后,将其隐藏。在Controller层添加afterrender事件来实现。代码中的tab_id可通过开发人员工具在ExtJS生成的页面源码中看到,这里是抛砖引玉,希望大家写出更好的选择器。
afterrender : function(){
Ext.get("tab_id").down(".x-tbar-loading").up(".x-btn").setVisible(false);
}
附上Ext.ux.data.PagingStore.js的源码:
/*
* PagingStore for Ext 4 - v0.6
* Based on Ext.ux.data.PagingStore for Ext JS 3, by Condor, found at
* http://www.sencha.com/forum/showthread.php?71532-Ext.ux.data.PagingStore-v0.5
* Stores are configured as normal, with whatever proxy you need for remote or local. Set the
* lastOptions when defining the store to set start, limit and current page. Store should only
* request new data if params or extraParams changes. In Ext JS 4, start, limit and page are part of the
* options but no longer part of params.
* Example remote store:
* var myStore = Ext.create('Ext.ux.data.PagingStore', {
model: 'Artist',
pageSize: 3,
lastOptions: {start: 0, limit: 3, page: 1},
proxy: {
type: 'ajax',
url: 'url/goes/here',
reader: {
type: 'json',
root: 'rows'
}
}
});
* Example local store:
* var myStore = Ext.create('Ext.ux.data.PagingStore', {
model: 'Artist',
pageSize: 3,
proxy: {
type: 'memory',
reader: {
type: 'array'
}
},
data: data
});
* To force a reload, delete store.lastParams.
*/
Ext.define('Ext.ux.data.PagingStore', {
extend: 'Ext.data.Store',
alias: 'store.pagingstore',
destroyStore: function () {
this.callParent(arguments);
this.allData = null;
},
/**
* Currently, only looking at start, limit, page and params properties of options. Ignore everything
* else.
* @param {Ext.data.Operation} options
* @return {boolean}
*/
isPaging: function (options) {
var me = this,
start = options.start,
limit = options.limit,
page = options.page,
currentParams;
if ((typeof start != 'number') || (typeof limit != 'number')) {
delete me.start;
delete me.limit;
delete me.page;
me.lastParams = options.params;
return false;
}
me.start = start;
me.limit = limit;
me.currentPage = page;
var lastParams = this.lastParams;
currentParams = Ext.apply({}, options.params, this.proxy ? this.proxy.extraParams : {});
me.lastParams = currentParams;
if (!this.proxy) {
return true;
}
// No params from a previous load, must be the first load
if (!lastParams) {
return false;
}
//Iterate through all of the current parameters, if there are differences, then this is
//not just a paging request, but instead a true load request
for (var param in currentParams) {
if (currentParams.hasOwnProperty(param) && (currentParams[param] !== lastParams[param])) {
return false;
}
}
//Do the same iteration, but this time walking through the lastParams
for (param in lastParams) {
if (lastParams.hasOwnProperty(param) && (currentParams[param] !== lastParams[param])) {
return false;
}
}
return true;
},
applyPaging: function () {
var me = this,
start = me.start,
limit = me.limit,
allData, data;
if ((typeof start == 'number') && (typeof limit == 'number')) {
allData = this.data;
data = new Ext.util.MixedCollection(allData.allowFunctions, allData.getKey);
data.addAll(allData.items.slice(start, start + limit));
me.allData = allData;
me.data = data;
}
},