直接监听 visibilitychange 事件是捕获标签页切换最准确方式,需绑定在 document 上并立即执行处理函数以覆盖初始状态,依赖 document.visibilitystate 判断 visible/hidden,服务端渲染需加 typeof document 保护。

直接监听 visibilitychange 事件就能可靠捕获用户切换标签页的行为,这是 HTML5 原生支持的最准确方式,无需轮询或模拟。
核心机制:用 visibilitychange 事件响应切换
浏览器在用户切走(如点开新标签、最小化窗口、锁屏)或切回当前页面时,会自动触发 document 上的 visibilitychange 事件。它不是“标签页切换专用”事件,但切换标签页正是最典型的触发场景之一。
- 事件必须绑定在
document上,写成document.addEventListener('visibilitychange', handler) - 不能绑定到
window或任意 DOM 元素——该事件不冒泡,也不支持委托 - 脚本需在 DOM 加载完成后注册,推荐放在
DOMContentLoaded回调内,或使用defer加载 script
状态判断:只依赖 document.visibilityState
document.visibilityState 是唯一可信的状态标识,现代浏览器中实际只有两个有效值:
- visible:页面处于前台标签页,且浏览器窗口未最小化
- hidden:页面被切换到后台、窗口最小化、设备锁屏,或被其他应用完全遮盖
不用 document.hidden 做主判断——它只是布尔值,已标记为 legacy;prerender 和 unloaded 在 Chrome 56+、Firefox、Safari 等主流引擎中早已废弃,代码里无需处理。
防漏处理:首次加载必须手动检查初始状态
页面加载完成时,可见性可能已是 hidden(例如 Chrome 预加载标签页、Firefox 休眠恢复),也可能卡在 visible(如 iOS Safari 锁屏后不发事件)。仅靠事件监听会错过初始状态。
- 注册事件监听后,立即调用一次处理函数:
handler() - 或在初始化时主动检查:
if (document.visibilityState === 'hidden') { /* 执行隐藏逻辑 */ } - 服务端渲染(如 Next.js)环境需加保护:
if (typeof document !== 'undefined')
典型使用示例(含关键兜底)
以下代码能稳定响应标签页切换,并兼顾卸载前补时、SPA 路由等真实场景:
if (typeof document !== 'undefined') {
let startTime = 0;
let totalVisibleTime = 0;
<p>const handleVisibilityChange = () => {
if (document.visibilityState === 'visible') {
startTime = performance.now();
} else {
const elapsed = performance.now() - startTime;
totalVisibleTime += elapsed;
}
};</p><p>// 立即执行一次,覆盖初始 hidden 状态
handleVisibilityChange();</p><p>document.addEventListener('visibilitychange', handleVisibilityChange);</p><p>// 页面卸载前兜底补上最后一段可见时间
window.addEventListener('beforeunload', () => {
if (document.visibilityState === 'visible') {
const elapsed = performance.now() - startTime;
totalVisibleTime += elapsed;
}
});
}</p>大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











