html5如何实现页面可见性检测_visibilitychange事件用法【教程】

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

页面可见性检测靠 document.visibilityStatevisibilitychange 事件

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 后台音频场景,应额外监听 pagehidepageshow 事件作为补充
  • 不能仅依赖 visibilityState === 'hidden' 就暂停计时器或取消动画——iOS 下可能根本不触发
  • 测试时务必真机验证,模拟器或桌面 Safari 行为差异大

Page Visibility API 相关的兼容性注意事项

所有现代浏览器都支持,但 IE10+ 仅支持带前缀的版本:msvisibilitychangemsHidden。不过 IE 已淘汰,除非维护遗留系统,否则可忽略前缀。

  • 检查支持性只需一行:'hidden' in document(返回 true 即表示支持)
  • document.hidden 是旧式布尔属性,已被 visibilityState 取代,但仍可读(返回 true 等价于 visibilityState === 'hidden'
  • SSR 渲染时注意:服务端没有 document,相关代码需包裹在 if (typeof document !== 'undefined') 中,否则报错
实际使用中最容易被忽略的是 iOS 的行为偏差和 SSR 环境下的执行时机——这两处不处理好,功能在真实用户场景中就会“看起来正常,实则失效”。