最简实现是抽离数据排序后重绘tbody:先用正则/date.parse识别列类型,空值排末尾;用闭包存列索引与升降序,点击清空所有th箭头再为当前列添加▲/▼;兼容ie11用slice.call替代array.from。

点击表头触发排序的最简实现
直接给 th 绑定 onclick,用原生 JavaScript 对 tbody 的 tr 重新排序,不依赖任何库。关键不是“怎么写完”,而是“怎么让排序结果和视觉对齐、支持多列、不崩 DOM”。
- 必须把数据从 DOM 中抽出来再排序,别直接操作
tr元素挪位置(容易丢失事件绑定或 input 值) - 排序前先记录当前列索引和升降序状态,用
data-sort或闭包存,别靠全局变量 - 每次排序后要重绘整段
tbody.innerHTML,而不是 appendChild 挪动旧节点(否则 checkbox、select 状态会丢)
处理字符串、数字、日期混合类型的判断逻辑
sort() 默认按字符串比较,"10" 会返回 <code>true,导致数字列排错。得先识别列内容类型,再决定用 Number()、Date.parse() 还是原样比。
- 检测是否为纯数字:用
/^-?\d+\.?\d*$/.test(cellText),注意负号和小数点 - 检测是否为常见日期格式(如
2023-05-12或12/05/2023):优先转成new Date(),失败则 fallback 到字符串比较 - 空值或非数字字符串统一排在末尾:
return a === b ? 0 : a === '' ? 1 : b === '' ? -1 : ...
保持表头箭头图标与排序状态同步
用户点两次同一列要切换升序/降序,箭头方向必须跟着变。别用 class 切换靠 CSS 伪元素画箭头(兼容性差),直接在 th 里插 ▲(▲)或 ▼(▼)更稳。
- 每次点击先清空所有
th的箭头:document.querySelectorAll('th').forEach(th => th.innerHTML = th.textContent) - 只给当前列加箭头:
th.innerHTML = `${th.textContent} ${isAsc ? '▲' : '▼'}` - 避免 innerHTML 清掉原有子元素(比如带 tooltip 的
span):改用textContent+appendChild(document.createTextNode(...))更安全
IE11 及以下不支持 Array.from() 怎么办
你写的 Array.from(tbody.querySelectorAll('tr')) 在 IE11 会报错。老浏览器得用 slice.call() 或手动遍历。
- 兼容写法:
var rows = [].slice.call(tbody.querySelectorAll('tr')) - 或者更稳妥:
var rows = []; for (var i = 0; i - 别用
for...of—— IE 不支持;也别用扩展运算符[...tbody.rows]—— 同样是 ES6+
真实项目里,如果还要支持 IE,连 String.prototype.trim() 都得 polyfill。但多数内部系统现在真没必要了——重点其实是别让排序逻辑和 DOM 更新耦合太死,方便以后替换成 table.sortData = [...] 这种数据驱动模式。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











