jQuery 多条件排序:按分数降序、时间升序对 div 元素进行复合排序

本文详解如何使用 jquery 对 dom 元素(如 `.contest_entry`)实现多级排序:优先按 `span.points` 数值**降序排列**,分数相同时再按 `span.times` 字符串(时间格式)**升序排列**,确保结果既准确又符合业务逻辑。

在实际开发中,单字段排序往往无法满足复杂展示需求。例如竞赛榜单需优先显示高分用户,而同分者则按完成时间更早者靠前——这就需要多条件复合排序。jQuery 本身不提供内置多级排序方法,但可通过 Array.prototype.sort() 的比较函数灵活实现。

核心思路是:在比较函数中逐级判断——先比主条件(points),若相等再比次条件(times)。注意两点关键细节:

  1. points 降序:用 rhsPoints - lhsPoints(而非 lhs - rhs),使数值大的排前面;
  2. times 升序:因原始 HTML 中时间为 " 09:55 " 这类带空格的字符串,直接字符串比较(如 "09:55" 天然有效,无需额外解析为 Date 对象(前提是格式统一为 HH:MM)。

以下是优化后的完整可运行代码(已修正原答案中错误的选择器 .child —— 示例 HTML 中并无 .child 容器):

$(function() {
  var sortedList = $('.contest_entry').toArray().sort(function(lhs, rhs) {
    // 提取并解析 points 值(注意 trim() 去除空格)
    var lhsPoints = parseInt($(lhs).find('span.points').text().trim(), 10);
    var rhsPoints = parseInt($(rhs).find('span.points').text().trim(), 10);

    if (lhsPoints === rhsPoints) {
      // points 相等时,按 times 升序:较早时间排前面
      var lhsTime = $(lhs).find('span.times').text().trim();
      var rhsTime = $(rhs).find('span.times').text().trim();
      return lhsTime > rhsTime ? 1 : -1; // 字符串比较,"09:55" < "17:20" → true
    } else {
      // points 降序:高分在前
      return rhsPoints - lhsPoints;
    }
  });

  $("#list").html(sortedList);
});

注意事项与最佳实践:

  • 使用 .trim() 清除 text() 返回的首尾空格,避免 parseInt(" 14 ") 虽可工作,但时间字符串 " 09:55 " 比较时空格可能导致意外结果;
  • 若 times 包含秒(如 "09:55:23")或跨日,建议改用 Date.parse() 或 moment.js 解析为毫秒再比较;
  • 排序后重新插入 DOM 会触发重排(reflow),大量元素时可考虑文档片段(documentFragment)优化性能;
  • 确保所有 .contest_entry 都包含 .points 和 .times 子元素,否则 parseInt(undefined) 会返回 NaN,导致排序异常——生产环境建议添加存在性校验。

最终排序效果示例(基于你的 HTML 数据):
19 分组内按时间升序 → "17:19"、"17:20"、"17:34";
16 分(09:55)排在 19 分之后、14 分(12:39)之前——完全符合「高分优先、同分早到优先」的业务规则。