page visibility api通过visibilitychange事件精准区分页面可见性与用户真实观看,结合performance.now()高精度计时、pagehide兜底及用户活跃信号(scroll/mousemove/keydown)过滤发呆时段,实现真实停留时长统计。

只靠页面加载到关闭的时间差,根本不算真实停留时长——用户切走标签、锁屏、最小化窗口,时间还在跑,但人早就不看了。Page Visibility API 的核心价值,就是帮你把“页面开着”和“用户真在看”区分开。
用 visibilitychange 控制计时开关
页面是否可见,不能靠轮询判断,必须监听标准事件:
- 绑定 document.addEventListener('visibilitychange', handler),这是唯一可靠方式
- 进入 visible 状态时,记录 performance.now() 作为起始或恢复点
- 进入 hidden 状态时,立即计算已过时长并累加到总时长中
- 首次加载后需手动检查 document.visibilityState,避免漏掉初始隐藏状态(比如用户从后台直接打开链接)
用 performance.now() 算高精度差值
Date.now() 可能被系统时间修改干扰,导致负数或跳变;performance.now() 是单调递增的高精度时钟,单位毫秒、小数精度达微秒级:
- 起始:startTime = performance.now()
- 暂停时:elapsed = performance.now() - startTime
- 两次调用差值稳定,不依赖系统时钟,适合做耗时测量
补全卸载前的最后一段可见时间
用户突然关掉标签页,visibilitychange 来不及触发。必须兜底监听页面即将离开的信号:
- 监听 pagehide(兼容性优于 beforeunload,且在 iOS Safari 中更可靠)
- 在回调里执行最后一次累加:totalDuration += performance.now() - startTime
- SPA 场景下,路由跳转不刷新页面,需在路由守卫中主动检查 visibilityState 并同步计时状态
排除“人在发呆”的假阅读(进阶)
仅靠可见性还不够——用户可能开着页面却盯着窗外。要逼近真实阅读,需叠加用户活跃信号:
- 监听 scroll、mousemove、keydown,任一触发就更新 lastActive 时间戳
- 设置空闲阈值(如 30 秒),若当前时间 − lastActive 超过该值,这段时长不计入阅读
- 起始计时点建议延后:首次滚动或聚焦后 2 秒再开始,过滤误入页面场景
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











