最直接方式是用 setInterval 每秒执行 new Date().toLocaleTimeString('zh-CN', {hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'Asia/Shanghai'}) 更新 textContent,同时监听 visibilitychange 事件控制定时器启停以避免跳秒。

用 setInterval 每秒更新 textContent 最直接
浏览器里动态显示秒级时间,核心就是每 1000ms 获取一次当前时间并写入 DOM。不用框架、不依赖外部库,setInterval 是最轻量可控的方式。注意别用 setTimeout 递归调用(容易漂移),也别设成 500ms 或更短(没必要且耗资源)。
常见错误是把 new Date() 写在定时器外,导致时间只取了一次初始值:
const now = new Date(); // ❌ 错!只执行一次
setInterval(() => {
el.textContent = now.toLocaleTimeString(); // 始终显示同一个时间
}, 1000);
正确做法是每次回调里重新构造 Date 对象:
const el = document.getElementById('clock');
setInterval(() => {
el.textContent = new Date().toLocaleTimeString(); // ✅ 每秒都新取
}, 1000);
toLocaleTimeString 的 hour12 和 timeZone 参数很关键
默认输出可能不符合预期:比如你在中国但显示美式 12 小时制,或时区错成 UTC。必须显式传参控制格式和时区,否则上线后用户看到的时间可能完全不对。
立即学习“前端免费学习笔记(深入)”;
-
hour12: false强制 24 小时制,避免上午/下午混淆 -
timeZone: 'Asia/Shanghai'确保国内用户看到东八区时间(哪怕系统时区被手动改过) - 省略
second字段会导致秒数不显示——它默认是true,但显式写上更稳妥
推荐写法:
new Date().toLocaleTimeString('zh-CN', {
hour12: false,
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
timeZone: 'Asia/Shanghai'
});
避免重排(reflow)性能问题:用 textContent,别用 innerHTML
如果容器里只有纯文本时间,用 innerHTML 会触发 HTML 解析、树重建,尤其在低端设备上可能卡顿。而 textContent 是纯文本赋值,开销极小。
另一个坑是把时间写进带样式的内联元素里(比如 <span class="sec">12</span>),再单独更新秒数——这需要 DOM 查询 + 属性操作,比整段替换还慢。保持结构扁平:
<div id="clock">14:23:05</div>
然后只做:
el.textContent = timeString; // ✅ 一行搞定,无解析、无查询
页面不可见时暂停定时器能省电又防跳秒
用户切到其他标签页后,Chrome 等浏览器会降频甚至暂停 setInterval,导致回来时秒数“跳变”(比如从 14:23:05 直接跳到 14:23:18)。这不是 bug,是浏览器优化。要平滑,得监听页面可见性状态。
用 document.hidden 判断,并配合 visibilitychange 事件:
- 页面隐藏时
clearInterval - 页面显示时重新
setInterval,并用new Date()同步一次时间(避免刚切回来就差好几秒)
这个逻辑虽小,但对用户体验影响明显——尤其仪表盘类页面,没人想看到时间突然往前蹦。



















