如何使用JavaScript实现点击按钮按指定列日期对表格排序
表格按指定列日期排序的可落地方案
之前方案失效的核心原因
- 你使用的日期格式为美式本地化格式
M/D/YYYY, h:mm:ss AM/PM,直接做字符串字典序排序会出现逻辑偏差:比如10/1/2021, 10:00:00 AM的字典序小于4/29/2021, 8:26:07 PM,会被错误排到前面,和真实时间先后完全不符 - 直接调用原生
Date.parse()解析该格式时,部分低版本浏览器会返回NaN,导致排序逻辑完全失效 - 原生数组排序如果没有提前把每行的日期文本转成可数值比较的时间戳,直接对DOM节点排序,就会出现顺序错乱、排序结果不符合预期的问题
完整可复用实现
不需要额外引入插件,纯原生逻辑即可跑通:
- 先在页面放置触发排序的按钮,设置id为
dateSortBtn - 配套的排序逻辑代码如下:
// 全局排序状态,用来切换升/降序 let isAsc = true; // 专门适配当前日期格式的解析逻辑,绕开浏览器自带Date解析的兼容问题 function parseFormattedDate(dateStr) { // 精准匹配你使用的日期格式:M/D/YYYY, h:mm:ss AM/PM const dateReg = /(\d{1,2})\/(\d{1,2})\/(\d{4}),\s(\d{1,2}):(\d{2}):(\d{2})\s(AM|PM)/; const match = dateStr.trim().match(dateReg); // 格式匹配失败的行统一排到最后 if (!match) return Number.MAX_SAFE_INTEGER; const [, month, day, year, hour12, minute, second, meridiem] = match; // 12小时制转24小时制的边界处理 let hour = parseInt(hour12); if (meridiem === 'AM' && hour === 12) hour = 0; // 午夜12点转0时 if (meridiem === 'PM' && hour !== 12) hour += 12; // 下午1点到11点转对应24小时制数值 // 生成标准日期对象(原生Date的月份从0开始计数,需要减1) const dateObj = new Date( parseInt(year), parseInt(month) - 1, parseInt(day), hour, parseInt(minute), parseInt(second) ); // 返回可做数值比较的时间戳,作为排序依据 return dateObj.getTime(); } // 排序按钮事件绑定 document.querySelector('#dateSortBtn').addEventListener('click', () => { const tableBody = document.querySelector('table tbody'); // 提取所有数据行(自动排除表头行) const rows = Array.from(tableBody.querySelectorAll('tr')); // 按第4列的日期时间戳排序 rows.sort((rowA, rowB) => { // 第4列对应的td索引为3(从0开始计数) const dateTextA = rowA.querySelectorAll('td')[3].textContent; const dateTextB = rowB.querySelectorAll('td')[3].textContent; const timeA = parseFormattedDate(dateTextA); const timeB = parseFormattedDate(dateTextB); // 根据当前排序状态决定比较方向 return isAsc ? timeA - timeB : timeB - timeA; }); // 按排序后的顺序重新插入DOM,完成表格重排 rows.forEach(row => tableBody.appendChild(row)); // 下次点击切换排序方向 isAsc = !isAsc; });
调试注意事项
- 读取单元格内容时优先使用
textContent,不要用innerText,避免单元格内嵌样式、标签影响纯日期文本的提取 - 注意DOM节点的索引规则:第4列对应的
<td>在行内的索引为3(从0开始计数),如果表格存在合并单元格、前置操作列的情况,要根据实际DOM结构调整对应的索引值 - 如果排序出现顺序完全随机的情况,先打印解析出来的时间戳值,确认有没有出现
NaN,大概率是正则的匹配规则和实际单元格里的文本有差异(比如文本里多了空格、标点不对) - 如果响应式表格有移动端虚拟滚动的情况,不要直接重排所有DOM,需要把排序逻辑作用在表格的原始数据源上,重新渲染视图即可,避免出现移动端滚动异常的问题
内容的提问来源于stack exchange,提问作者slade
相关产品推荐
相关产品推荐

