ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

从计时器失效到判断页面可见性

2026/8/7 0:16:49 拓冰建站 浏览量
从计时器失效到判断页面可见性

目录

  • 1,问题 - 计时器失效
  • 2,解决 - 页面可见性判断
    • 1,页面可见性
    • 2,visibilitychange
    • 3,终极解决方案 - lifecycle
  • 3,精准计时

1,问题 - 计时器失效

问题复现:移动端必现,pc 端和浏览器版本有关(公司电脑必现,家里的没有复现)。

通过 setTimeoutsetInterval 实现的倒计时,会在页面隐藏后,实测会延缓计时或经过15s 左右会停止计时,导致计时不准确!直到页面再次激活。

2,解决 - 页面可见性判断

可以通过判断页面可见性,计算出经过的隐藏时间来重置倒计时的时间点。

1,页面可见性

无论使用 pc 还是移动端,都会有当前页面被隐藏的情况:

  • 切换 tab 页
  • 浏览器最小化
  • 切换到其他应用
  • 点击链接跳转到其他页面

2,visibilitychange

MDN 参考

document.addEventListener("visibilitychange", () => {// 页面可见if (document.visibilityState === "visible") {console.log("visible");} else {console.log("hidden");}
});

举例:计算隐藏时间

<body><div id="box">100</div><script>const box = document.getElementById("box");// 初始时间let count = 100;const inerval = setInterval(() => {if (count <= 0) {box.innerHTML = "倒计时结束";clearInterval(inerval);document.removeEventListener("visibilitychange", visibilitychange);return;}box.innerHTML = count--;}, 1000);let startTime2Hidden = 0; // 页面隐藏瞬间的时间let count2Hidden = 0; // 记录页面隐藏瞬间的 count 值document.addEventListener("visibilitychange", visibilitychange);function visibilitychange() {if (document.visibilityState === "visible") {const minus = parseInt((new Date().getTime() - startTime2Hidden) / 1000);count = count2Hidden - minus; // 正确经过的时间} else {startTime2Hidden = new Date().getTime();count2Hidden = count;}}</script>

visibilitychange 的问题:在 safari 浏览器下,这个事件不总是触发,比较怪异。

3,终极解决方案 - lifecycle

谷歌实验室开源项目,兼容性很好。

使用举例:

<script src="./lifecycle.es5.js"></script>
<script>lifecycle.addEventListener("statechange", function (event) {console.log(event.oldState, event.newState);if (event.oldState == "passive" && event.newState == "hidden") {console.log("hidden");} else if (event.oldState == "hidden" && event.newState == "passive") {console.log("visibile");}});
</script>

3,精准计时

无论使用哪种解决方案,倒计时都不是准确的,因为用户可能会修改本地时间,况且 js 计时本身就不精准。

要实现精准计时,还得靠后端接口返回正确的时间(后端也会做校验)。

以上面这个问题来说,另一种解决方案:在页面激活时再次请求一次倒计时相关的接口,前端重置倒计时时间点。


以上。