推荐使用 visibilitychange + beforeunload 结合 performance.now() 统计用户真实停留时长:页面可见时计时,隐藏时暂停,卸载前用 sendbeacon 上报;避免在 beforeunload 中使用 fetch 或 xhr。

可以用 BOM 中的 window.performance 和 beforeunload(或 visibilitychange)事件来较准确地统计用户在当前页面的真实停留时长。
利用 performance.navigation 和时间戳记录起始时间
页面加载完成时记录当前时间,作为访问起点。推荐使用 performance.now()(高精度)或 Date.now()(兼容性更好):
let startTime = performance.now(); // 或 Date.now()
// 也可放在 DOMContentLoaded 或 load 事件中确保页面已就绪
window.addEventListener('load', () => {
startTime = performance.now();
});监听页面离开或不可见状态以计算停留时长
单纯靠 beforeunload 不可靠(如刷新、跳转、崩溃可能不触发),更健壮的做法是结合 visibilitychange + beforeunload:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 当页面变为隐藏(
document.hidden === true)时,记录当前时间并暂停计时 - 当页面重新可见,继续计时(可选,若需总活跃时长)
- 在
beforeunload中发送最终时长(注意:该事件中仅支持同步请求,如navigator.sendBeacon)
let totalTime = 0;
let lastVisibleTime = performance.now();
<p>document.addEventListener('visibilitychange', () => {
if (document.hidden) {
// 页面隐藏,累加已可见时长
totalTime += performance.now() - lastVisibleTime;
} else {
// 页面重新可见,重置起始点
lastVisibleTime = performance.now();
}
});</p><p>window.addEventListener('beforeunload', () => {
if (!document.hidden) {
totalTime += performance.now() - lastVisibleTime;
}
// 使用 sendBeacon 确保数据可靠发出(不阻塞卸载)
navigator.sendBeacon('/log-visit', JSON.stringify({
duration: Math.round(totalTime / 1000), // 秒为单位
url: window.location.href,
timestamp: Date.now()
}));
});</p>补充说明与注意事项
-
sendBeacon是首选方式,它在页面卸载前异步发送数据,且不依赖网络请求状态 - 避免使用
fetch或XMLHttpRequest在beforeunload中发请求,它们很可能被浏览器取消 - 如果后端不支持接收 beacon 请求体(如只接受 query 参数),可用
URLSearchParams构造 GET 请求路径 - 移动端切后台、浏览器标签切换、系统休眠等都会触发
visibilitychange,覆盖多数真实场景
简单 fallback:仅用时间差(适合基础统计)
若无需高精度活跃时长,只需“从打开到关闭”的粗略值,可简化为:
const start = Date.now();
window.addEventListener('beforeunload', () => {
const duration = Math.round((Date.now() - start) / 1000);
navigator.sendBeacon('/log', `duration=${duration}`);
});不复杂但容易忽略 visibility 变化的影响,实际业务中建议优先采用 visibilitychange 方案。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










