用 requestAnimationFrame 配合 Date.now() 差值计算实现精准计时,避免 setInterval 后台节流;用 toLocaleTimeString() 自动适配本地时区与语言;用 textContent 替代 innerHTML 减少 DOM 开销。

直接用 setInterval + new Date() 更新 DOM 就能实现,但多数人卡在时区、格式、性能这三处——尤其页面挂后台后时间停走或跳变,不是代码没跑,是浏览器节流了。
为什么 setInterval 显示的时间会变慢或跳秒?
浏览器在标签页非激活状态(比如切到其他 tab 或最小化)时,会限制 setInterval 的最低执行间隔(通常 ≥ 1000ms),导致每秒更新变成“勉强每秒一次”,累积误差明显。
- 别用
setInterval(() => { update() }, 1000)做精准计时 - 改用
requestAnimationFrame配合时间差计算:每次回调取Date.now(),和上一次时间比对,只在真正过了一秒时才更新 DOM - 示例逻辑:
let lastTime = Date.now();<br>function tick() {<br> const now = Date.now();<br> if (now - lastTime >= 1000) {<br> updateDisplay();<br> lastTime = now;<br> }<br> requestAnimationFrame(tick);<br>}<br>tick();
如何让时间显示符合本地时区且不手动算偏移?
toLocaleTimeString() 是最省心的选择,它自动读取用户系统时区和语言偏好,不需要解析 getTimezoneOffset() 或拼接 UTC 字符串。
- 避免手写
date.getHours() + ':' + date.getMinutes()...—— 容易漏掉补零、忽略夏令时、错失 locale 差异(比如阿拉伯数字 vs. 拉丁数字) - 推荐写法:
new Date().toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' }) - 如果只要小时分钟,删掉
second项即可;想加年月日,换用toLocaleDateString()或合并用toLocaleString()
DOM 更新太频繁导致卡顿?试试 textContent 而不是 innerHTML
时间字符串不含 HTML 标签,用 innerHTML 会触发 HTML 解析和 DOM 重建,哪怕内容完全一样,开销也比 textContent 高数倍。
立即学习“前端免费学习笔记(深入)”;
- 错误写法:
el.innerHTML = timeStr; - 正确写法:
el.textContent = timeStr; - 若容器里混有其他 HTML(比如图标、单位文字),把时间部分单独包一层
<span id="clock"></span>,只更新这个节点
真正难的不是“显示时间”,而是让它在后台页、低功耗设备、多语言用户面前都稳定准确——requestAnimationFrame 防节流、toLocaleTimeString 防时区错、textContent 防重绘,三个点漏一个,用户就会觉得“这时间不准”。



















