用原生 JavaScript 实现表格排序需监听表头点击事件(事件委托)、通过 Array.from(tbody.rows) 转换 HTMLCollection 为数组、按列索引提取 textContent 并处理数字/空值,再用 sort() 排序后重插 DOM;注意 IE 兼容性、大数据量节流及复杂表头场景下的数据行筛选。

直接给表格加排序,不需要引入任何库,用原生 sort() 配合 Array.from() 和 dataset 就能搞定,但关键在「点哪一列就排哪一列」和「切换升/降序」这两个逻辑容易写错。
点击表头触发排序:监听 th 的 click 事件
不要给每个 th 单独绑定事件,用事件委托最稳妥——监听整个 thead 或 table,再判断 event.target 是否为 th:
document.querySelector('table').addEventListener('click', e => {
if (e.target.tagName === 'TH') {
const columnIndex = Array.from(e.target.parentNode.children).indexOf(e.target);
sortTableByColumn(columnIndex);
}
});
注意:e.target 可能是 th 里的文字或图标,所以要用 e.target.closest('th') 更安全;columnIndex 是从 0 开始的列索引,后续用于取 td 值。
提取并排序数据行:Array.from(tbody.rows) 是关键
tbody.rows 是 HTMLCollection,不能直接调用 sort(),必须转成数组。常见错误是漏掉这一步,导致排序无效:
立即学习“Java免费学习笔记(深入)”;
- 用
Array.from(tbody.rows)或[...tbody.rows]转数组 - 排序前先用
rows.forEach(row => tbody.removeChild(row))清空旧顺序(否则 append 会追加) - 排序函数里用
row.cells[columnIndex].textContent.trim()取值,注意去空格 - 数字列要转
Number(),否则按字符串排(比如 "10"
维护排序状态:用 th.dataset.sort 记录当前方向
每次点击同一列,要在升序 ↔ 降序之间切换。别用全局变量存状态,把状态挂到 th 上最干净:
Twitter Bootstrap无疑是最好用的前端开发框架,其中对表格的预设样式也是非常的好看,可以满足我们日常的界面风格,但是实际项目中,我们可能需要动态的加载Table表格里面的内容,然后需要有个排序的功能。
function sortTableByColumn(index) {
const th = document.querySelectorAll('th')[index];
const direction = th.dataset.sort === 'asc' ? 'desc' : 'asc';
th.dataset.sort = direction;
// 排序逻辑...
rows.sort((a, b) => {
let aVal = a.cells[index].textContent.trim();
let bVal = b.cells[index].textContent.trim();
if (!isNaN(aVal) && !isNaN(bVal)) {
aVal = Number(aVal); bVal = Number(bVal);
}
return direction === 'asc' ? aVal > bVal : aVal < bVal;
});
}
注意:aVal > bVal 返回布尔值,但 sort() 需要返回 -1 / 0 / 1,更稳妥写法是 (aVal bVal ? 1 : 0);如果列里混有空值或“-”,得提前处理,否则 NaN 会导致排序错乱。
IE 兼容性和性能提醒
IE11 不支持 dataset(可用 getAttribute('data-sort') 替代),也不支持箭头函数和展开运算符;如果目标用户还用 IE,就别用 [...rows],改用 Array.prototype.slice.call(rows)。
表格超过 500 行时,每次点击都重排 + 重插 DOM 会卡顿。真实项目里建议加节流,或只对前端展示做虚拟排序(不操作 DOM,用 display: none 控制可见行)。
最常被忽略的是:表头合并(colspan)、固定表头、服务端分页这些场景下,直接操作 tbody.rows 会出错——排序前务必确认你操作的是实际参与排序的数据行,而不是所有 tr。









