jQuery 多条件排序:按分数降序、时间升序排列 DOM 元素

本文详解如何使用 jquery 对 `.contest_entry` 元素进行多级排序:优先按 `span.points` 数值**降序**(高分在前),分数相同时再按 `span.times` 字符串**升序**(早时间在前)。

在实际前端开发中,仅按单一字段排序往往无法满足业务需求。例如竞赛榜单需“先看得分高低,得分相同再比用时长短”,这就要求实现多条件稳定排序。jQuery 本身不提供原生多字段排序方法,但可通过 Array.prototype.sort() 的比较函数自定义逻辑完成。

核心思路是:在比较函数中逐级判断——先比较主条件(points),若相等则进入次条件(times),避免直接混合计算导致逻辑混乱。

以下是优化后的完整实现(已修正原答案中错误的 .child 选择器,并增强健壮性):

$(function() {
  const sortedList = $('.contest_entry').toArray().sort((lhs, rhs) => {
    // 提取并解析 points 值(确保非 NaN)
    const lhsPoints = parseInt($(lhs).find('span.points').text().trim(), 10) || 0;
    const rhsPoints = parseInt($(rhs).find('span.points').text().trim(), 10) || 0;

    // 主排序:points 降序 → 即 rhs - lhs(注意:原题要求“大数在前”)
    if (lhsPoints !== rhsPoints) {
      return rhsPoints - lhsPoints;
    }

    // 次排序:times 升序(字符串比较适用于 HH:MM 格式,且假设格式统一)
    const lhsTime = $(lhs).find('span.times').text().trim();
    const rhsTime = $(rhs).find('span.times').text().trim();

    // 字符串字典序可正确比较 '09:55' < '12:39' < '17:19' 等(因固定两位时分)
    return lhsTime.localeCompare(rhsTime);
  });

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

关键说明与注意事项:

  • .toArray() 是必需的:jQuery 对象需转为原生数组才能调用 sort();
  • parseInt(..., 10) + || 0 防止空文本或非法字符导致 NaN,避免排序异常;
  • trim() 清除前后空格(如示例中 " 12:39 "),保障时间字符串准确比较;
  • localeCompare() 替代 >/:更语义化、兼容性更好,且对字符串排序更可靠;
  • 时间格式前提:本方案假设 times 均为 HH:MM 格式(如 '09:55' 能正确小于 '12:39')。若含秒或不等宽(如 '9:55'),建议统一转换为分钟数再比较:
    const parseTimeToMinutes = t => {
      const [h, m] = t.trim().split(':').map(Number);
      return (h || 0) * 60 + (m || 0);
    };
    return parseTimeToMinutes(lhsTime) - parseTimeToMinutes(rhsTime);

最终排序结果将严格遵循:
① 分数从高到低;
② 分数相同时,时间从早到晚(如 09:55 排在 17:19 之前)。

此模式可轻松扩展至三级及以上条件(如再按用户名字母序),只需在 if-else if-else 链中追加判断即可,具备良好可维护性与可读性。