倒计时需后端返回时间戳或标准日期字符串,前端用统一 setInterval 每500ms更新可见区域带 countdown-cell 类的单元格,templet 仅静态渲染初始值并标记 data-end,销毁时清除定时器。
倒计时字段必须是时间戳或可解析的日期格式
layui 的 table 渲染不支持在列定义中直接执行异步或持续更新的逻辑,所以不能靠 templet 一次性渲染完就一劳永逸。倒计时要“实时”,本质是定时重绘某几列 —— 但注意:不是重载整个表格,否则卡顿且丢失滚动位置、选中状态等。
关键前提是后端返回的字段得是明确的时间点,比如 end_time: 1717023600000(毫秒时间戳)或 end_time: "2024-05-30 15:00:00"。如果返回的是“还剩 2 天”,那前端无法计算,也不可控。
- 推荐统一用毫秒时间戳,避免浏览器本地时区解析歧义
- 若用字符串,务必确保格式能被
new Date(str)正确解析("2024-05-30T15:00:00"安全,"2024-05-30 15:00:00"在 Safari 可能失败) - 不要在
templet里写setInterval—— 每行都开一个定时器,表格翻页或重渲染时极易泄漏
用 table.on('rendered') 启动统一倒计时管理器
倒计时应集中控制:只启一个 setInterval,每次遍历需要更新的单元格,算差值并写入 DOM。触发时机选在表格完成渲染后,而不是初始化时 —— 因为初始数据可能为空,或分页后才加载真实数据。
示例做法:
table.on('rendered', function(obj){
// 清除旧定时器(防止重复绑定)
if (window.countdownTimer) clearInterval(window.countdownTimer);
<p>window.countdownTimer = setInterval(function(){
// 遍历所有带倒计时类名的 td
$('.layui-table-body tbody tr').each(function(){
var $td = $(this).find('.countdown-cell');
if ($td.length === 0) return;</p><pre class="brush:php;toolbar:false;"> var endTime = +$td.data('end'); // 假设存了 data-end="1717023600000"
var remain = Math.max(0, endTime - Date.now());
var text = remain <p>}, 500); // 500ms 更新一次,平衡精度和性能
});</p>
- 给对应列的
templet加上class="countdown-cell"和data-end="{{d.end_time}}" - 间隔设为 500ms 而非 1000ms,可避免“跳秒”感(如 2.9s → 1.9s)
- 表格销毁(如切换 tab、路由离开)时记得
clearInterval(window.countdownTimer),否则内存泄漏
templet 中只做静态快照,不启动定时逻辑
很多人误在 templet 函数里写 setInterval 或直接调用 formatRemain(Date.now()),这会导致两问题:一是首次渲染显示的是“当前剩余”,之后再也不变;二是每个单元格独立计时,页面卡顿。
正确写法是仅输出初始状态 + 标记信息:
{field:'end_time', title:'截止时间', templet: function(d){
return '<span class="countdown-cell" data-end="' + d.end_time + '">' +
formatRemain(d.end_time - Date.now()) +
'</span>';
}}
-
formatRemain()是纯函数,输入毫秒差,输出“2天3小时”之类字符串 - 不依赖全局状态,不操作 DOM,不发请求,不设定时器
- 确保
d.end_time是数字类型(后端传错成字符串会导致NaN)
移动端和长列表下的性能与兼容性注意点
倒计时对性能敏感:每 500ms 查找并更新上百个 .countdown-cell 元素,在低端安卓机或 Chrome 低配模式下可能掉帧。实际项目中容易忽略的是“不可见区域仍参与计算”。
- 用
getBoundingClientRect()粗筛:只更新top 0的行 - 避免用 jQuery 的
$().text()批量更新,改用原生el.textContent,快 3–5 倍 - Layui 2.8+ 表格开启
height: 'full-xx'时,.layui-table-body是固定高滚动容器,需监听其scroll事件来节流重绘 - iOS Safari 对
requestAnimationFrame支持更稳,但setInterval在后台标签页会降频(可能 10s 才触发一次),倒计时不准属正常现象
最常被跳过的细节:没处理倒计时归零后的自动刷新动作(比如触发按钮变灰、发送通知)。这个逻辑不能塞进倒计时循环里,应该单独监听 remain ≤ 0 后调用一次业务回调,并清除对应单元格的定时更新标记。











