页面可见性检测依赖 document.visibilityState 和 visibilitychange 事件,需绑定在 document 上,支持值为 'visible'、'hidden' 等,但 iOS 存在误判,SSR 需判断环境。

页面可见性检测靠 document.visibilityState 和 visibilitychange 事件
HTML5 提供了原生的页面可见性 API,不需要轮询或定时器。核心是两个东西:document.visibilityState(当前状态值)和监听 visibilitychange 事件。它比 blur/focus 更精准——比如用户切换到另一个标签页、最小化窗口、锁屏,甚至某些浏览器中打开开发者工具,都可能触发该事件。
visibilitychange 事件监听必须绑定在 document 上
这个事件不会冒泡到 window,也不能用 addEventListener 绑在任意 DOM 元素上。只对 document 有效,且建议在脚本加载后尽早注册,避免漏掉初始状态变化。
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
console.log('页面变为可见');
} else if (document.visibilityState === 'hidden') {
console.log('页面被隐藏');
}
});
-
visibilityState可能的值有:'visible'、'hidden'、'prerender'(已废弃,现代浏览器基本不返回)、'unloaded'(极少见) - 首次加载时不会触发
visibilitychange,但你可以直接读取document.visibilityState获取初始状态 - 不要在事件回调里做耗时操作,比如发起网络请求或重绘大量 DOM,因为该事件可能在后台频繁触发(如 Chrome 中快速切回标签)
常见误判场景:Safari/iOS 的特殊行为
iOS Safari 对 visibilityState 的判断更保守。比如页面进入后台后,可能长时间维持 'visible';又或者播放视频/音频时,即使切到其他 App,visibilityState 仍为 'visible'(因媒体仍在运行)。这会导致你基于可见性做的逻辑失效。
- 若需兼容 iOS 后台音频场景,应额外监听
pagehide和pageshow事件作为补充 - 不能仅依赖
visibilityState === 'hidden'就暂停计时器或取消动画——iOS 下可能根本不触发 - 测试时务必真机验证,模拟器或桌面 Safari 行为差异大
与 Page Visibility API 相关的兼容性注意事项
所有现代浏览器都支持,但 IE10+ 仅支持带前缀的版本:msvisibilitychange 和 msHidden。不过 IE 已淘汰,除非维护遗留系统,否则可忽略前缀。
立即学习“前端免费学习笔记(深入)”;
- 检查支持性只需一行:
'hidden' in document(返回true即表示支持) -
document.hidden是旧式布尔属性,已被visibilityState取代,但仍可读(返回true等价于visibilityState === 'hidden') - SSR 渲染时注意:服务端没有
document,相关代码需包裹在if (typeof document !== 'undefined')中,否则报错










