不能用 标签实现倒计时,因其仅用于静态时间语义;应使用 setInterval 结合 Date.now() 计算剩余毫秒数,并通过 textContent 更新显示,过期时清除定时器并设终止文案。

用 标签显示倒计时?别这么干
是语义化标签,用来标记**静态的时间点或时间区间**(比如发布日期、活动开始时间),浏览器不会自动更新它,也不支持动态倒计时。强行往里面塞 JS 更新的文本,反而破坏语义——屏幕阅读器会读出“2025-04-05T14:30”,而不是“还剩 2 小时 17 分”。真要用语义化,得配合 datetime 属性存原始时间,视觉部分另起炉灶。
倒计时核心:用 setInterval 算差值 + textContent 更新 DOM
最轻量、兼容性最好、也最容易控制的方式。关键不是“怎么显示”,而是“怎么算”和“怎么不卡”:
- 用
Date.now()算当前毫秒数,减去目标时间戳,避免依赖系统时钟同步(new Date()构造慢且易受本地时区/修改干扰) - 别用
setTimeout递归模拟定时器——误差会越滚越大;setInterval虽然也有漂移,但至少节奏可控 - 每次更新前先判断是否已过期,过期就
clearInterval并写死文案(比如“已结束”),否则继续跑 - 格式化建议封装成小函数,避免内联拼接:
formatDuration(ms)返回"02:17:05"这种字符串
requestAnimationFrame
- 用户切到其他 tab 时,
requestAnimationFrame会被浏览器节流甚至暂停,倒计时直接“卡住”,而setInterval在后台仍按毫秒级推进(只要页面没被完全冻结) - 每秒调用 60 次
requestAnimationFrame去检查时间差,纯属浪费——你并不需要每帧都更新,用户也看不出 16ms 和 1000ms 更新一次的区别 - 如果硬要用,必须搭配
performance.now()+ 上次记录时间做差值补偿,代码复杂度陡增,得不偿失
倒计时文案要可访问,但不是靠
想让视障用户知道“还剩 3 分 22 秒”,正确做法是:
- 保持视觉文案清晰(如
03:22) - 用
aria-live="polite"让屏幕阅读器感知变化: - 在 JS 中每次更新时,同步设置
aria-label(比如el.setAttribute('aria-label', '剩余 3 分钟 22 秒')),比塞进更直接有效 - 别忘了加
role="timer",这是 ARIA 规范里专为倒计时定义的角色
真正容易被忽略的,是过期后是否清除了定时器、是否重置了 aria-live 区域、以及服务端时间与客户端时间偏差超过分钟级时该怎么对齐——这些不处理,倒计时看着动,其实早就不准了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











