前言
我们有时候需要处理页面离开事件,在这里对常用的事件进行一个差异分析。
在移动端开发中,beforeunload 事件监听在 Android 和 iOS 平台存在显著差异,主要体现在事件支持度、触发场景和替代方案上。以下是关键差异总结及兼容性解决方案:
一、平台支持差异
| 平台/事件 | beforeunload | pagehide | visibilitychange |
|---|---|---|---|
| android | 仅支持页面刷新 | 全支持 | 页面隐藏触发 |
| ios | 全版本不支持 | 全支持(关闭/刷新/跳转) | 关闭无效 |
| pc浏览器 | 全支持 | 全支持 | 页面隐藏触发 |
iOS 特殊限制:
由于安全策略,iOS 的 Safari 及 WebView 完全不触发 beforeunload 和 unload 事件,需用 pagehide 替代。
二、事件触发场景差异
-
Android:
beforeunload:仅在 页面刷新 时触发,关闭 Tab 或浏览器不触发 。- 关闭操作需依赖
visibilitychange(切后台)或pagehide(关闭 Tab)。
-
iOS:
- 所有关闭操作(关闭 Tab、刷新、跳转)仅触发
pagehide。 - 微信浏览器中,左上角关闭按钮也通过
pagehide监听 。
- 所有关闭操作(关闭 Tab、刷新、跳转)仅触发
三、推荐兼容方案:多事件联合监听
结合 beforeunload、pagehide、visibilitychange 事件,并通过标志位避免重复执行:
let isEventFired = false;
function handlePageExit() {
if (isEventFired) return;
isEventFired = true;
// 执行数据上报或清理逻辑
sendExitData(); // 使用 sendBeacon 确保可靠性
}
// Android/PC 优先使用 beforeunload
window.addEventListener('beforeunload', handlePageExit);
// iOS 和 Android 备用方案
window.addEventListener('pagehide', handlePageExit);
// 应对切后台场景(Android 和 HarmonyOS)
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
handlePageExit();
} else {
isEventFired = false; // 重置标志位
}
});
四、关闭时发送请求的注意事项
1、异步请求不可靠:
页面关闭时异步 AJAX 可能被中断,尤其在 iOS 中。
2、同步请求被废弃:
现代浏览器(如 Chrome)已禁止在 beforeunload 中发送同步 XHR 。
3、替代方案:navigator.sendBeacon()
优势:异步发送且不阻塞页面卸载,支持 Android/iOS(iOS 11+)。
限制:数据量 ≤ 64KB,类型需为 Blob 或 FormData 。
function sendExitData() {
const data = new Blob([JSON.stringify({ event: 'exit' })], { type: 'application/json' });
navigator.sendBeacon('https://api.example.com/log', data);
}
4、iOS 的同步 AJAX 技巧:
若必须用 AJAX,需在 pagehide 中强制改为同步(不推荐,可能影响体验):
window.addEventListener('pagehide', () => {
$.ajaxSetup({ async: false }); // 关闭异步
// 发送请求...
});
五、各场景事件支持总结
| 用户操作 | android支持事件 | ios支持事件 |
|---|---|---|
| 刷新页面 | beforeunload + pagehide | pagehide |
| 关闭 Tab | pagehide | pagehide(iOS 14+) |
| 切后台/退出浏览器 | visibilitychange | visibilitychange(仅切后台) |
| 微信内关闭 | visibilitychange | pagehide |
关键结论:
- Android:组合使用
beforeunload+pagehide+visibilitychange。- iOS:仅依赖
pagehide,配合sendBeacon上报数据。- 微信浏览器:iOS 用
pagehide,Android 用visibilitychange78。
通过多事件联合监听 + sendBeacon,可覆盖 95% 以上的关闭场景,剩余极端情况(如 iOS 强制杀进程)无法捕获需业务降级处理。