锁定老帖子 主题:GT-Grid 1.0 基础教程(九)
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-07-28
教程说明: 这是一个告诉大家如何快速的利用GT-Grid开发列表的基础教程.以后会推出"高级教程". 查看其他教程,以及最新版本信息,请点击这里 第九章: 排序 第一章中的示例 就已经具备排序功能了, 但是只是简单的客户端排序. 客户端排序处理的数据并不一定时"当前页的数据", 而是"所有在客户端的数据",也就是说,当你将数据全部加载到客户端,在客户端进行分页时,客户端排序实际上排列的就是所有数据. 本章将讲解 自定义排序函数 以及如何进行 服务端排序. 将上一章编写的"mydemo8.html"另存为"mydemo9.html". ========================================= 先来说一个 很重要 但是很简单的属性:columns定义中的 "sortable" 属性, 顾名思义,当不希望某一列可排序时,就把那一列的该属性设置为 false, 本例中不希望对"详细信息"列进行排序,那么可如下定义: var colsConfig ={ /* ... 略去其他属性设置 ...*/ { id : 'detail' , header : "详细信息" , width : 120, sortable : false, renderer : function(value ,record,columnObj,grid,colNo,rowNo){ return ' <a href=".?no='+record['no']+'" style="margin-left:3px;" > '+ record['name'] +' 的详细信息 </a>'; } } ]; ========================================= 下面说一说自定义排序函数. GT-Grid 自身只提供了两种数据排序方式 : 按数字数据排序 和 按字符串数据排序. 这两种排序显然无法应对多样的需求, 所以GT-Grid 提供了一个 接口函数,columns定义中的 : getSortValue( value, recrod ) 开发人员重写该接口,就可以实现自定义的更加复杂的排序方式. 例如有这样一个需求 : 按照姓名的字符串长度排序. 那么我们可以这么定义 姓名 列: var colsConfig ={ /* ... 略去其他属性设置 ...*/ { id : 'name' , header : "姓名" , width : 100 , editable:false , editor: { type :'text' ,validRule : 'R' } , getSortValue : function(value , record){ return value?value.length:0; } }, ]; getSortValue函数的两个参数分别为: value :当前记录中,该列对应的数据 record : 排序时的 当前记录. 在上例中, 排序时,取响应数值时就不再是 取记录的"name"值,而为变为了取name的字符串长度,从而实现了按姓名字符长度排序的功能. 在这里就暂时先不列举更复杂的例子了. ========================================= 下面该说一说 服务端排序了. 要使用服务端排序,需要 将 grid的 remoteSort 属性设置为 true. var gridConfig={ /* ... 略去其他属性设置 ...*/ remoteSort : true } 下一步要知道 排序信息 传递到后台的格式, 以及后台如何处理这些信息了. 排序信息 是和 load信息 一起提交到后台的 其格式如下(注意看 sortInfo 部分: { action : 'load', pageInfo : { /* ... 略去pageInfo信息 ...*/ }, sortInfo : [ { columnId : "排序的列id" , fieldName : "排序的列对应的dataset中的field字段名" , sortOrder : "asc" // 排序的顺序状态 : 升序"asc" 降序"desc" 默认"defaultsort" } ] } 大家可能注意到了, sortInfo信息对应的是一个数组, 这是为了将来做多重排序而准备的. 在目前版本(1.1之前),该数组最多只会有一组排序信息. 后台得到这个信息之后, 可以把 sortInfo 转换为一个 List对象. 而这个list的第一个元素 就是排序的信息了, 然后开发人员就可以根据这些排序信息来实现服务端的排序了. (与服务端结合的完整示例 会有与此相关的参考实现) 看一下示例中的 GridServerHandler 类下的 initSortInfo方法 和 getSingleSort 方法 大家应该可以更好的理解读取sortInfo信息的原理. ========================================= 关于服务端的排序 就先讲到这里, 下一章将讲解的是过滤功能(客户端和服务端)的实现. . 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-07-30
呵呵,我觉得一个组件要强大,要被更多的人应用,详细的文档是第一位的,国外的开源社区一般都会有详细的文档与支持,这点对于开发者来说,非常重要。
持续关注GT。。 |
|
返回顶楼 | |
发表时间:2008-07-30
getSortValue 这个方法有点不明白,value和record 2个名称是否就是js array sort里面接受function的2个参数?
比如按照拼音排序: function(a,b){return a.localeCompare(b)} |
|
返回顶楼 | |
发表时间:2008-07-30
不是的 你可以理解为getSortValue 的返回值是 a 或 b
record1 = { age : 11 } record2 = { age : 22 } 正常的 按 age的升序排序 那么结果是 record1 ,record2 但是 如果 你在 getSortValue 里 写上 getSortValue = function(v,r){ return 0-v; // v == r['age'] } 那么结果就是 record2 和 record1 了 也就是 在排序时 从 record1中取age时 取得不再是 record1的真正的age了 而是经过 getSortValue 处理过的值 |
|
返回顶楼 | |
发表时间:2008-07-30
为什么不采用标准的sort方法呢?javascript/java都是用这种标准方法。
而且按我的理解,你这种接口是按照取得值,再来做一个sort,这样会导致一些排序无法实现,比如我前面提到的按照拼音排序。 |
|
返回顶楼 | |
发表时间:2008-07-30
Quake Wang 你的理解还是有偏差
我的这个做法 只比你说的那种更简单易用 如果非要说有什么缺点 那就是 "可能会慢一点 因为用到了双层闭包的引用" 我说个例子 你就明白了 "按姓名的拼音排序" 假设 你已经写好了一个方法 , 传入 汉字 取得拼音: getPinYin(cnstr) 那么 你在 name列的getSortValue 只要这么写就可以: getSortValue : function(value,r){ return getPinYin(value); // 此时value 其实就是那各个记录的姓名了; } 如果按你的思路是不是要这样写: sort : function(r1,r2){ var pinyin1 = getPinYin( r1['name'] ); var pinyin2 = getPinYin( r2['name'] ); return pinyin1 <pinyin2 ? -1 : (pinyin1 >pinyin2?1:0); } 你比较一下 你觉得哪个好呢??? |
|
返回顶楼 | |
发表时间:2008-07-30
这不是一个讨论简单或者易用的问题,我想要表达的是:接口设计要符合大家的习惯。
大家都已经习惯的写法:比如javascript Array.sort接受一个function(a, b),比如Java的Arrays.sort接受一个Comparator#public int compare(Object o1, Object o2),没有必要引入新的学习成本。 另外,就算从简单或者易用来讨论,这个设计也有问题: 你的设想是所有排序都是通过一个方法调用获取一个值,然后再对值进行排序。但实际上,这个调用在一些情况下面是不必要甚至是写不出来的,比如前面的按照拼音排序,localeCompare是js自己带的功能,可以写成这样: sort: function(r1, r2) { return r1['name'].localeCompare(r2['name']; } 如果要用你原先的设计,我还得去自己实现一个通过字符获取拼音映射值的功能,那样就太麻烦了。 |
|
返回顶楼 | |
发表时间:2008-07-30
如果只是排序一次很好办
升序 降序 默认排序 多重排序 这些问题如果你自己写sort 你要处理很多问题 例如 取得当前的排序状态,然后判断 如果是这样那么... 如果是那样那么... 如果是主排序... 如果是第2排序 如果是第3排序... |
|
返回顶楼 | |
发表时间:2008-07-30
多重排序可以用组合,假设已经有了现成的3个单列排序:
nameSort: function(r1, r2) { return r1['name'].localeCompare(r2['name']; } ageSort: function(r1, r2) { return r1['age'] - r2['age']; } workYearSort: function(r1, r2) { return r1['workYear'] - r2['workYear']; } 我们可以写一个通用的multiSort: function multiSort() { var args = Array.prototype.slice.call(arguments); return function(a,b) { for (var i=0;i<args.length;i++) { var result = args[i](a,b); if (result!=0) return result; } return 0; } } 调用可以是: multiSort(nameSort,ageSort,workYearSort); 主排序,第2排序,第3排序,可以通过调整3个参数的顺序实现。 正序/倒序的问题,可以再写一个: function negative(func) { return function(a,b) { var i = func(a,b); return i == 0 ? i : -i; } } 调用就是: multiSort(nameSort,negative(ageSort),workYearSort); 这2个方法都可以在gtgrid中提供,使用者不需要关心他们的实现,只要实现单个栏位的排序即可。我不知道用你的方法做多重排序是否会更简单?能否举例说明一下? p.s 以上代码未经调试,仅做示例,这些其实在各种UI工具里面都是用类似思路(比如swing/swt的table sort)。 |
|
返回顶楼 | |
发表时间:2008-07-30
你的这个思路我明白 你说的那些技术手段我也明白
但是我目前的设计中, 希望用户更专注于"在排序时,一条记录,参与排序的值是什么". 因为 这个是排序最核心的东西 , 也是与排序算法 和语言无关的 对排序最自然的理解方式. 而不希望用户去关注 "在排序时,如何决定任意两条之间记录之间的顺序" 更不希望用户去理解和了解 "更多的关于 多重排序等其他的排序细节". 而且 ,我觉得编写 sort 函数所需要掌握的内容 明显要更多 要明白 sort 函数的用法 返回值的意义 而且 你这些都是建立在下列基础之上的: 1 用户明白js自带的排序方式的原理 (这个请相信我 不是所有人都明白的) 2 系统使用js默认的 array.srot( ... )方法进行排序. 以上两点 有任何一点不明白 都不行. 另外关于 多种排序 和 多重排序等 只是我举的例子 (按你的思路 面对这几个例子时,用户需要写的东西已经很多了, 要比 getSortValue复杂很多) 实际上还有很多更复杂的操作 是我要在 sort 时做的 , 而这些 都不能暴露给客户的, 例如对sort值的缓存 值的类型转换 ... 等等.如果这些都让用户来做, 我绝对对于用户的要求 以及自定义函数的成本太高了. 再而且, 给客户越多低层的东西 我要面临的问题越多. " 客户自己写的sort函数有问题, 他自己没检查出来, 会跟你说"排序不好用" 要代码, "对不起 系统保密 代码不能给你" 于是 两个人开始了文字和语言的交流, 耗时一个上午之后 终于明白了原因... " 这种情况在产品开发里太常见了,而我希望极力避免这种问题 其实 你的需求 可以实现的 有一个 sortFunction 你只要重写他就可以了 但是 我不会把这种给"达人"准备的方法暴露给客户的. 其实 你想想 利用override 有什么是不能实现的呢? 只是 开发者是否希望用户那么做而已. (你买来的正版windows中 绝对不会送你一本"注册表修改权威指南 以及windows优化指南的"对吧? 为什么呢???) 说这么多 已经超出了技术的范畴.更多的是我对"产品"的一个设计上的理念. 总之 在GT目前的整体架构中(以及我的设计理念) 你提出的这种做法 我是不会采用的. |
|
返回顶楼 | |