jQuery: 不用插件实现任意列表或表格的排序
jQuery sort <table>
and <ul>
简介
jQuery实现任意列表或表格实际上非常容易,不需要专门的插件,代码也很短。本站的[文章目录]的排序就是用jQuery实现的。
表格排序
示例代码
$(document).on('click','th',function(){
var table = $(this).parents('table').eq(0);
var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()));
this.asc = !this.asc;
if (!this.asc){rows = rows.reverse();}
table.children('tbody').empty().html(rows);
});
function comparer(index) {
return function(a, b) {
var valA = getCellValue(a, index), valB = getCellValue(b, index);
return $.isNumeric(valA) && $.isNumeric(valB) ?
valA - valB : valA.localeCompare(valB);
};
}
function getCellValue(row, index){
return $(row).children('td').eq(index).text();
}
代码分析
概览
一般来说,表格<table>
的结构是:
<table>
<thead>
<tr>
<th>head1</th>
<th>head2</th>
...
</tr>
</thead>
<tbody>
<tr>
<td>data1</td>
<td>data2</td>
...
</tr>
<tr>
...
</tr>
...
</tbody>
</table>
我们希望点击表头就可以对对应的列进行排序,所以通过
$(document).on('click','th',function(){});
监听表头点击
当点击表头时,我们可以通过
var table = $(this).parents('table').eq(0);
获得这个表格的<table>
元素
接来下我们希望找到所有列表项,即<tbody>
中的所有<tr>
:
var rows = table.find('tr:gt(0)');
然后就可以对这些<tr>
排序了:
var rows = table.find('tr:gt(0)').toArray().sort();
[array.sort(compareFunction)]是javascript本身支持的方法,我们只需要自定义compareFunction
即可实现我们想要的排序。首先我们需要知道对哪一列进行排序,即点击的表头所在的列:
$(this).index()
这样得到列序号后,即可调用compareFunction
,如:
var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()));
这样就完成了对所有<tr>
的排序。
为了实现可以递增和递减排序,我们可以让每次点击时排序方式都反向,即:
this.asc = !this.asc;
if (!this.asc){rows = rows.reverse();}
最后我们用排序后的<tr>
替换原始的<tr>
:
table.children('tbody').empty().html(rows);
即实现了整个排序过程。
comparer()
array.sort(compareFunction)
中compareFunction
接受两个参数,都是array
中的元素,但示例中的comparer()
只接受一个元素。实际上comparer()
只是将真正用来排序的函数包装了起来,而comparer()
的用处就是制定排序的列。
通过
getCellValue(a, index)
可以得到这个<tr>
第index
列的实际值。
为了实现可以对数字和字符串进行排序,我们用
$.isNumeric(valA) && $.isNumeric(valB) ?
valA - valB : valA.localeCompare(valB);
得到,即如果比较的两个对象都是数值型或可转换为数值型,就以相减的结果作为排序的顺序(javascript中字符串相减会首先将字符串转换为数值型,这样就不用手动转换了);如果有对象不是数值型,则以本地特定的顺序以字符串的形式排序。
getCellValue()
getCellValue()则是需要用户自己定义的,如果你的表格很简单,就可以直接套用示例,但如果你的表格内元素比较复杂,你就需要自己写jQuery选择器,找到你想要用来比较的内容了。
示例中
$(row).children('td').eq(index).text();
则是从row
这一行,找到第index
列的值。
DEMO
[jQuery sort table - JSFiddle]
列表排序
示例代码
$(document).on('click', 'button', function() {
var ul = $('#this-ul');
var rows = ul.children('li').toArray().sort(comparer);
this.asc = !this.asc;
if (!this.asc) {
rows = rows.reverse();
}
ul.empty().html(rows);
});
function comparer(a, b) {
var valA = getCellValue(a),
valB = getCellValue(b);
return $.isNumeric(valA) && $.isNumeric(valB) ?
valA - valB : valA.localeCompare(valB);
}
function getCellValue(row) {
return $(row).find('.first').text();
}
代码分析
这个和上面的表格排序大同小异,就不再具体解释了。需要注意的地方就是找到<ul>
元素,以及自定义的getCellValue()
。
DEMO
[jQuery sort ul - JSFiddle]
明明return function(a,b)中 a和b都是undefined的 ,为什么最后却变成了tr了呢?
因为comparer()返回的是一个函数(函数指针),而这个函数是作为sort()的参数使用的,当sort()中指定参数为函数(function)时,sort()会潜在调用function(a, b),这时a和b就是被排序数组中的两个元素,由function(a, b)返回比较大小的结果,这样就完成了排序。如果你以Java的角度来看这段代码的话多半是看不懂的,因为Java不支持“闭包”,在这里就是Java不支持函数作为返回值或函数参数;而如javascript和python等是支持的。
谢谢
提个小问题,第一个例子,当第一列数字是1,2,3排列的时候,第一次点击无效,这是什么原因,我没找出来
应该是你的节点没找对,注意js获取节点的方法用对,有文本节点和标签节点的,不知道是不是这个问题
你好,我看DEMO(https://jsfiddle.net/zhantong/zpbw3h7t/)第一次点击没有问题呀~