用setInterval每秒更新innerHTML最直接,核心是new Date()获取实时时间并用toLocaleTimeString()格式化显示,需立即执行一次避免首屏空白,且定时器必须设为1000毫秒以平衡精度与性能。

用 setInterval 每秒更新 innerHTML 最直接
浏览器里动态显示当前时间,核心就两条:获取时间、定时刷新。不用框架、不依赖外部库,setInterval 配合 new Date() 就够用。关键不是“能不能”,而是“怎么避免卡顿和时区错乱”。
常见错误是把格式化逻辑写在 setInterval 外面,导致时间只初始化一次;或者用 setTimeout 递归但没清上一个定时器,造成多个定时器叠加。
- 把
new Date()放进定时器回调里,确保每次取实时值 - 用
toLocaleTimeString()而不是手动拼接getHours()等,自动适配用户本地时区和12/24小时制 - 定时器间隔设为
1000(毫秒),别用500或100——秒针跳动不需要亚秒级精度,反而增加 CPU 负担
<div id="clock"></div>
<script>
const el = document.getElementById('clock');
function update() {
el.innerHTML = new Date().toLocaleTimeString();
}
update(); // 立即执行一次,避免首屏空白
setInterval(update, 1000);
</script>需要精确到毫秒?别用 setInterval 硬扛
如果页面要显示“00:00:00.000”这种带毫秒的时间,setInterval 的实际执行时机不可控,误差可能达 10–50ms,数字会跳、不同步。
正确做法是:用 setInterval 每秒触发一次“校准”,再用 performance.now() 或 Date.now() 动态算差值。
立即学习“前端免费学习笔记(深入)”;
- 记录上一次校准的
Date.now()和对应毫秒数 - 每次触发时,用当前
Date.now()减去基准值,取模 1000 得到当前毫秒偏移 - 只在整秒时刻更新秒数部分,毫秒部分靠计算补全,视觉更稳
注意:performance.now() 返回浮点数,精度高但不能直接转时间字符串;Date.now() 是整数,更适合做差值计算。
服务端时间不准?得靠 API 同步,前端无法自修正
用户设备时间可能被手动调快/调慢,甚至关机后 RTC 漂移。如果你需要显示“服务器当前时间”(比如倒计时活动开始),仅靠前端 new Date() 一定不准。
- 必须从后端接口返回一个标准时间戳(如
{ serverTime: 1717023456789 }) - 前端拿到后,立刻记录本地
Date.now(),算出偏差值offset = serverTime - Date.now() - 后续所有时间显示都用
new Date(Date.now() + offset)计算 - 每 5–10 分钟重新请求一次接口,防止长期运行后偏差累积
这个 offset 不是固定值——网络延迟会影响首次同步精度,所以第一次响应后最好等 2–3 秒再采样第二次,取平均。
Vue/React 项目里别在模板里写 new Date()
像 {{ new Date().toLocaleTimeString() }} 这种写法在 Vue 模板或 React JSX 中看似方便,实则危险:它不会自动重渲染,除非你手动触发响应式更新,否则永远只显示初始值。
- Vue 用户应把时间存在
ref或data里,用onMounted启动定时器并更新该响应式变量 - React 用户用
useState+useEffect,清理函数里必须调用clearInterval,否则组件卸载后定时器还在跑 - 不要在 render 函数里调用
new Date(),那是反模式,既不可控又难调试
最易忽略的一点:SPA 页面切路由时,旧组件的定时器若没清除,会持续占用内存和 CPU,尤其在低端安卓机上明显发热降频。



















