
本文详解如何使用 jquery 对 dom 元素(如 .contest_entry)实现多级排序:优先按 points 降序排列,points 相同时再按 times 升序(即耗时更短者优先)。
在实际前端开发中,仅按单一字段排序往往无法满足业务需求。例如竞赛排行榜需“先看得分高低,得分相同时比用时长短”,这就要求我们实现多条件复合排序。jQuery 本身不提供原生多字段排序方法,但可通过 Array.prototype.sort() 的比较函数自定义逻辑——关键在于正确处理比较优先级与返回值。
以下为优化后的完整解决方案(已修正原答案中的选择器错误,并增强健壮性):
$(function() {
var sortedList = $('.contest_entry').toArray().sort(function(lhs, rhs) {
// 提取 points 值(确保非 NaN)
var lhsPoints = parseInt($(lhs).find('span.points').text().trim(), 10) || 0;
var rhsPoints = parseInt($(rhs).find('span.points').text().trim(), 10) || 0;
// 主排序:points 降序(大 → 小)
if (lhsPoints !== rhsPoints) {
return rhsPoints - lhsPoints;
}
// 次排序:times 升序(早 → 晚),需将时间字符串标准化为可比较格式
var lhsTimeStr = $(lhs).find('span.times').text().trim();
var rhsTimeStr = $(rhs).find('span.times').text().trim();
// 简单字符串比较适用于 HH:MM 格式(前提是格式统一且补零)
// 更健壮做法:转换为 Date 对象或分钟数
var parseTimeToMinutes = function(timeStr) {
var match = timeStr.match(/^(\d{1,2}):(\d{2})$/);
if (!match) return Infinity;
var hour = parseInt(match[1], 10);
var minute = parseInt(match[2], 10);
return hour * 60 + minute;
};
var lhsMinutes = parseTimeToMinutes(lhsTimeStr);
var rhsMinutes = parseTimeToMinutes(rhsTimeStr);
return lhsMinutes - rhsMinutes; // 升序:小时间在前
});
$("#list").html(sortedList);
});✅ 关键说明:
- 选择器修正:原答案中 .find(".child span.points") 是错误的(HTML 中无 .child 容器),应直接使用 .find('span.points');
- 空值防护:使用 || 0 防止 parseInt(undefined) 返回 NaN 导致排序异常;
- 时间解析强化:直接字符串比较 "09:55" "12:39" 会出错。因此推荐统一转为分钟数比较,兼容性更强;
- 排序稳定性:.sort() 在现代浏览器中是稳定排序(相同键值相对顺序不变),适合多级排序场景。
? 注意事项:
- 若 times 包含秒或 AM/PM,需扩展 parseTimeToMinutes 函数支持;
- 大量元素(>1000)排序建议结合虚拟滚动或后端分页,避免阻塞主线程;
- 可封装为 jQuery 插件(如 $.fn.sortByFields)提升复用性。
通过以上实现,示例数据将按预期排序:19分(17:19)→ 19分(17:20)→ 19分(17:34)→ 16分(09:55)→ 14分(12:39),精准满足“高分优先、同分比快”的业务规则。










