能省,但需主动响应visibilitychange事件——浏览器只通知页面隐藏,不自动停定时器、动画等;必须手动关停高频、视觉密集、持续占用CPU/GPU或网络的逻辑,如轮询、requestAnimationFrame、视频播放、WebGL渲染及非关键埋点。
能省,但得你主动响应 visibilitychange 事件——浏览器不会自动停掉定时器、动画或请求,它只负责告诉你“页面现在看不见了”。关键不是 API 本身多强大,而是你有没有在 hidden 状态下及时关停那些“用户看不到却还在拼命跑”的逻辑。
重点盯住高频、视觉密集、持续占用 CPU/GPU 或网络的逻辑:
cancelAnimationFrame(id) 即可停掉,GPU 占用会立刻下降。video.pause() 或 audio.pause()。别设 currentTime = 0,否则丢失用户进度。render() 调用,避免无意义 GPU 持续工作。visible 状态再批量发送,减少小包请求和电量开销。现代浏览器(Chrome/Firefox/Edge/Safari 13.1+)已统一支持标准事件名,可直接使用:
document.addEventListener('visibilitychange', () => {if (document.visibilityState === 'hidden') { /* 停资源 */ }
else { /* 恢复资源,注意防重复启动 */ }
});
若需兼容 IE10 或老旧 Android WebView,需做前缀探测:
先检查 document.hidden 是否存在;不存在则跳过。再用 ['', 'webkit', 'ms', 'moz'].find(...) 找出当前前缀,注册带前缀的事件(如 webkitvisibilitychange)。
visibilitychange 是信号,不是指令——它不保证实时触发,快速切两次标签页,事件可能被合并或延迟几毫秒;它也不代表页面即将卸载(那是 pagehide 或 beforeunload 的职责)。
常见错误包括:
document.hidden = true 能手动模拟隐藏(实际是只读属性,设了无效);<div hidden> 和 document.visibilityState——前者只是 CSS 显隐,后者是浏览器窗口级生命周期状态;visible,导致逻辑失效。不要一刀切停所有定时器。可按业务重要性分级:
Set 或数组集中管理活跃的 interval 和 raf ID,便于统一清理和恢复。