extjs版本2.1
用extjs的分组store加载数据遇到一个问题,首先store定义如下:
var store = new Ext.data.GroupingStore({ reader: new BidResultItemXmlReader(), url: Ipms.StateAssetOfficeService + '/QueryBidResultItem', sortInfo: { field: 'id', direction: "DESC" }, groupField: 'groupField' });
单从字面分析这段代码:从url加载数据,并且按id进行降序排序,然后按groupField字段分组。
但是最终页面展现的数据,却不是这样的,如下图:
而后台发送的数据的确是按id降序排列的。
原因就是对Ext排序、分组不够了解,仅仅从字面上进行臆断。
1.Store.js中加载数据的方法loadRecords()源码如下:
loadRecords : function(o, options, success){ // ... this.applySort(); // 会调用GroupingStore的方法 // .. }
2.GroupingStore.js中applySort()源码:
applySort : function(){ Ext.data.GroupingStore.superclass.applySort.call(this); if(!this.groupOnSort && !this.remoteGroup){ var gs = this.getGroupState(); if(gs && gs != this.sortInfo.field){ // 凶手 this.sortData(this.groupField); // 调用Store的方法 } } },
从源码可知,只要我们的排序字段跟分组字段不是相同列的话,他都会再次按分组字段排序。
3.Store.js中sortData()源码:
// private sortData : function(f, direction){ direction = direction || 'ASC'; var st = this.fields.get(f).sortType; var fn = function(r1, r2){ var v1 = st(r1.data[f]), v2 = st(r2.data[f]); return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0); }; this.data.sort(direction, fn); if(this.snapshot && this.snapshot != this.data){ this.snapshot.sort(direction, fn); } },
4. 之所以进行分组之前首先按分组字段进行排序,个人臆断原因有二。
A. 排序字段跟分组字段不同,即使排好序后,分组还是有可能打破排序的顺序的。
B. 跟GroupingView的写法有关系,见下文。
5.GroupingView.js的doRender()源码(有删减):
doRender : function(cs, rs, ds, startRow, colCount, stripe){ var groups = [], curGroup, i, len, gid; for(i = 0, len = rs.length; i < len; i++){ var rowIndex = startRow + i; var r = rs[i], gvalue = r.data[groupField], g = this.getGroup(gvalue, r, rowIndex, colIndex, ds); if(!curGroup || curGroup.group != g){ // 关键 curGroup = { group: g, gvalue: gvalue, groupId: gid, startRow: rowIndex, rs: [r] }; groups.push(curGroup); }else{ curGroup.rs.push(r); } r._groupId = gid; } }
此方法就是构造分组列表,简单的说,他会循环GroupStore中的每个条目,判断如果groupField的值跟当前组的值相同,则把此条目放入当前分组;否则的话,新建一个分组。
他这么做,就是假设store是按照groupField进行了排序。从applySort()方法中,我们发现他会强制按groupField进行升序排序。这也正是导致最终视图的原因。
6.说些风凉话。在服务端排序在客户端分组,事件很不靠谱的事儿。Ext的处理方式就更不靠谱了(简单看了一下3.2中的处理就优雅多了)。
7. 折中的办法:按照某个字段分组,然后组内的条目按照某某字段分组。所以,干脆把排序和分组要么都放在服务器端,客户端不处理;要么都放在客户端,服务器端不干预。
8.我们采用排序和分组都在服务器端完成,有一定的局限性
var store = new Ext.data.GroupingStore({ reader: new BidResultItemXmlReader(), url: Ipms.StateAssetOfficeService + '/QueryBidResultItem', sortInfo: { field: 'id', direction: "DESC" }, remoteSort: true, // 配置1 remoteGroup: true,// 配置2 groupField: 'groupField' });