如何判断用户是否离开了当前页面?
在现代 Web 开发中,我们常常需要知道用户是否还停留在当前页面。这个看似简单的需求,背后却关联着用户体验、数据分析和系统性能等多个重要方面。
什么是“离开页面”?
“离开页面”并不仅仅指关闭浏览器,它包含多个场景:
- 切换到其他浏览器标签页或应用(页面变为不可见)。
- 最小化浏览器窗口。
- 关闭标签页或整个浏览器。
- 当前页面跳转到新的 URL。
- 移动端切换至其他 App 或返回主屏。
针对这些不同场景,Web 平台提供了多种技术和 API 来进行判断与响应。
方法一:Page Visibility API —— 判断页面是否可见
Page Visibility API 是判断用户是否正在查看当前页面的标准方式。
核心 API
document.hidden // 页面是否处于隐藏状态
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
console.log('用户离开了当前页面(切换标签页或最小化)');
pauseMyVideo(); // 例如暂停视频播放
} else {
console.log('用户回到了当前页面');
playMyVideo(); // 例如恢复播放
}
});
应用场景
- 页面变为不可见时暂停动画/视频。
- 页面恢复时继续加载数据或轮播。
- 节省资源(电量与带宽)。
优缺点
优点 | 缺点 |
---|---|
标准化、浏览器广泛支持 | 无法区分“切换标签页”与“关闭页面” |
性能友好,不阻塞主线程 |
方法二:beforeunload
和 unload
—— 离开页面前的经典方案
1. beforeunload
事件
用户关闭页面、刷新或跳转时触发,可用于提醒用户不要误操作离开。
window.addEventListener('beforeunload', (event) => {
event.preventDefault();
event.returnValue = ''; // 显示浏览器默认的提示框
});
⚠️ 现代浏览器不允许自定义提示文本,且此交互会打断用户体验。
2. unload
事件
页面卸载过程中触发,一般用于清理逻辑。
window.addEventListener('unload', () => {
console.log('用户正在离开页面');
// 不要在此发异步请求!
});
❌ 不推荐 用于发送分析请求或重要数据,因为异步请求往往无法完成。
方法三:navigator.sendBeacon()
—— 安全可靠的离开上报
为了确保在页面卸载时仍能安全发送数据,可以使用 navigator.sendBeacon()
。
示例代码
window.addEventListener('pagehide', () => {
const data = JSON.stringify({ type: 'leave', timestamp: Date.now() });
navigator.sendBeacon('/log', data);
});
sendBeacon 特点
- 异步、非阻塞
- 浏览器在卸载页面时仍会尽量发送
- 适用于日志分析、心跳监控等“最后一刻”的数据采集
方法四:pagehide
和 pageshow
—— 应对“往返缓存”(bfcache)
当用户使用浏览器的“前进/后退”按钮时,浏览器可能直接使用缓存恢复页面,而不是重新加载。这种机制被称为 bfcache(Back-Forward Cache)。
代码示例
window.addEventListener('pagehide', (event) => {
if (event.persisted) {
console.log('页面被缓存(bfcache)');
} else {
console.log('页面正常卸载');
}
navigator.sendBeacon('/log', JSON.stringify({ action: 'leave' }));
});
✅
pagehide
比unload
更可靠,尤其在移动端。
最佳实践总结
场景 | 推荐做法 |
---|---|
页面是否可见? | 使用 Page Visibility API |
离开页面时上报数据 | 使用 sendBeacon() + pagehide |
防止误操作离开 | 使用 beforeunload ,但要慎用 |
清理资源 | 尽量避免 unload ,用 pagehide 替代 |
最后的话
页面“是否可见”与“是否离开”在技术上是两个不同层面的问题。合理组合这些 API,可以帮助我们:
- 提升用户体验(比如暂停视频)
- 节省资源(如停止轮询)
- 保证数据完整性(可靠日志上报)
推荐组合:
document.addEventListener('visibilitychange', handleVisibilityChange);
window.addEventListener('pagehide', sendLeaveData);