12.4 使用 HTML5 自定义数据属性
到目前为止,我们一直在使用表格中单元格的内容来确定排序的方式。虽然通过苦心设计,已经实现了根据内容对表格行进行正确的排序,但通过让服务器输出带有HTML5 data-
*属性的HTML,可以让代码更加有效。我们例子中用到的第二个表格包含如下属性:
<table id="t-2" class="sortable">
<thead>
<tr>
<th></th>
<th data-sort='{"key":"title"}'>Title</th>
<th data-sort='{"key":"authors"}'>Author(s)</th>
<th data-sort='{"key":"publishedYM"}'>Publish Date</th>
<th data-sort='{"key":"price"}'>Price</th>
</tr>
</thead>
<tbody>
<tr data-book='{"img":"2862_OS.jpg",
"title":"DRUPAL 7","authors":"MERCER DAVID",
"published":"September 2010","price":44.99,
"publishedYM":"2010-09"}'>
<td><img src="images/2862_OS.jpg" alt="Drupal 7"></td>
<td>Drupal 7</td>
<td>David Mercer</td>
<td>September 2010</td>
<td>$44.99</td>
</tr>
<!-- code continues -->
</tbody>
</table>
注意,除第一个之外的其他<th>
元素,现在都包含data-sort
属性;而每个<tr>
元素则都包含data-book
属性。我们最早介绍自定义数据属性是在第7章,当时是通过这种属性为插件提供数据。而在这里,我们要使用jQuery取得这些属性的值。为取得这些属性,需要把属性名中data-
之后的部分传给.data()
方法。例如,$('th').first().data('sort')
就是要取得第一个<th>
元素的data-sort
属性。
在通过.data()
方法取得数据属性的值时,jQuery会视情况把相应的值转换成数值、数组、对象、布尔值或null
。为了让jQuery把数据属性的值转换为对象,属性值字符串必须使用有效的JSON格式。为此,要把数据属性的值放在单引号中,而把每个键和字符串值放在双引号中:
<th data-sort='{"key":"title"}'>
由于jQuery会把这个JSON字符串转换成对象,因此取得其中的值就很简单了。比如,要取得key
属性的值,可以这样写:
$('th').first().data('sort').key
在以这种方式取得了自定义属性的值之后,相应的数据就会被jQuery在内部保存起来,不会再访问或修改相应HTML的data-*
属性了。
使用像这里这样的数据属性的一个最大好处是,这些值可以输出为不同于表格单元格内容的形式。换句话说,我们对前面第一个表格所做的细节处理——把字符串转换为全部大写、改变日期的格式以及把价格转换为数值,都已经被处理好了。这样,我们就可以写出更简洁、高效的排序代码,参见代码清单12-8。
代码清单12-8
- $(document).ready(function() {
- var $table2 = $('#t-2');
- var $headers = $table2.find('thead th').slice(1);
- $headers
- .wrapInner('<a href="#"></a>')
- .addClass('sort');
- var rows = $table2.find('tbody > tr').get();
- $headers.on('click', function(event) {
- event.preventDefault();
- var $header = $(this),
- sortKey = $header.data('sort').key,
- sortDirection = 1;
- if ($header.hasClass('sorted-asc')) {
- sortDirection = -1;
- }
- rows.sort(function(a, b) {
- var keyA = $(a).data('book')[sortKey];
- var keyB = $(b).data('book')[sortKey];
- if (keyA < keyB) return -sortDirection;
- if (keyA > keyB) return sortDirection;
- return 0;
- });
- $headers.removeClass('sorted-asc sorted-desc');
- $header.addClass(sortDirection == 1 ? 'sorted-asc' : 'sorted-desc');
- $.each(rows, function(index, row) {
- $table2.children('tbody').append(row);
- });
- });
- });
这种方法简单而直观:通过$header.data('sort').key
取得sortKey
,然后利用这个变量去比较$(a).data('book')[sortKey]
和$(b).data('book')[sortKey]
。这样做,由于在调用sort
函数之前不必首先遍历每一行并调用sortKeys
中保存的一个函数,所以效率的提升是显而易见的。这种简单加上高效率,同时也造就了代码的高性能和容易维护。