12.4 使用 HTML5 自定义数据属性

到目前为止,我们一直在使用表格中单元格的内容来确定排序的方式。虽然通过苦心设计,已经实现了根据内容对表格行进行正确的排序,但通过让服务器输出带有HTML5 data-*属性的HTML,可以让代码更加有效。我们例子中用到的第二个表格包含如下属性:

  1. <table id="t-2" class="sortable">
  2. <thead>
  3. <tr>
  4. <th></th>
  5. <th data-sort='{"key":"title"}'>Title</th>
  6. <th data-sort='{"key":"authors"}'>Author(s)</th>
  7. <th data-sort='{"key":"publishedYM"}'>Publish Date</th>
  8. <th data-sort='{"key":"price"}'>Price</th>
  9. </tr>
  10. </thead>
  11. <tbody>
  12. <tr data-book='{"img":"2862_OS.jpg",
  13. "title":"DRUPAL 7","authors":"MERCER DAVID",
  14. "published":"September 2010","price":44.99,
  15. "publishedYM":"2010-09"}'>
  16. <td><img src="images/2862_OS.jpg" alt="Drupal 7"></td>
  17. <td>Drupal 7</td>
  18. <td>David Mercer</td>
  19. <td>September 2010</td>
  20. <td>$44.99</td>
  21. </tr>
  22. <!-- code continues -->
  23. </tbody>
  24. </table>

注意,除第一个之外的其他<th>元素,现在都包含data-sort属性;而每个<tr>元素则都包含data-book属性。我们最早介绍自定义数据属性是在第7章,当时是通过这种属性为插件提供数据。而在这里,我们要使用jQuery取得这些属性的值。为取得这些属性,需要把属性名中data-之后的部分传给.data()方法。例如,$('th').first().data('sort')就是要取得第一个<th>元素的data-sort属性。

在通过.data()方法取得数据属性的值时,jQuery会视情况把相应的值转换成数值、数组、对象、布尔值或null。为了让jQuery把数据属性的值转换为对象,属性值字符串必须使用有效的JSON格式。为此,要把数据属性的值放在单引号中,而把每个键和字符串值放在双引号中:

  1. <th data-sort='{"key":"title"}'>

由于jQuery会把这个JSON字符串转换成对象,因此取得其中的值就很简单了。比如,要取得key属性的值,可以这样写:

  1. $('th').first().data('sort').key

在以这种方式取得了自定义属性的值之后,相应的数据就会被jQuery在内部保存起来,不会再访问或修改相应HTML的data-*属性了。

使用像这里这样的数据属性的一个最大好处是,这些值可以输出为不同于表格单元格内容的形式。换句话说,我们对前面第一个表格所做的细节处理——把字符串转换为全部大写、改变日期的格式以及把价格转换为数值,都已经被处理好了。这样,我们就可以写出更简洁、高效的排序代码,参见代码清单12-8。

代码清单12-8

  1. $(document).ready(function() {
  2. var $table2 = $('#t-2');
  3. var $headers = $table2.find('thead th').slice(1);
  4. $headers
  5. .wrapInner('<a href="#"></a>')
  6. .addClass('sort');
  7. var rows = $table2.find('tbody > tr').get();
  8. $headers.on('click', function(event) {
  9. event.preventDefault();
  10. var $header = $(this),
  11. sortKey = $header.data('sort').key,
  12. sortDirection = 1;
  13. if ($header.hasClass('sorted-asc')) {
  14. sortDirection = -1;
  15. }
  16. rows.sort(function(a, b) {
  17. var keyA = $(a).data('book')[sortKey];
  18. var keyB = $(b).data('book')[sortKey];
  19. if (keyA < keyB) return -sortDirection;
  20. if (keyA > keyB) return sortDirection;
  21. return 0;
  22. });
  23. $headers.removeClass('sorted-asc sorted-desc');
  24. $header.addClass(sortDirection == 1 ? 'sorted-asc' : 'sorted-desc');
  25. $.each(rows, function(index, row) {
  26. $table2.children('tbody').append(row);
  27. });
  28. });
  29. });

这种方法简单而直观:通过$header.data('sort').key取得sortKey,然后利用这个变量去比较$(a).data('book')[sortKey]$(b).data('book')[sortKey]。这样做,由于在调用sort函数之前不必首先遍历每一行并调用sortKeys中保存的一个函数,所以效率的提升是显而易见的。这种简单加上高效率,同时也造就了代码的高性能和容易维护。