移动端beforeunload、pagehide、visibilitychange事件差异分析

229 阅读2分钟

前言

我们有时候需要处理页面离开事件,在这里对常用的事件进行一个差异分析。

在移动端开发中,beforeunload 事件监听在 Android 和 iOS 平台存在显著差异,主要体现在事件支持度触发场景替代方案上。以下是关键差异总结及兼容性解决方案:

 一、平台支持差异

平台/事件beforeunloadpagehidevisibilitychange
android仅支持页面刷新全支持页面隐藏触发
ios全版本不支持全支持(关闭/刷新/跳转)关闭无效
pc浏览器全支持全支持页面隐藏触发

iOS 特殊限制
由于安全策略,iOS 的 Safari 及 WebView 完全不触发 beforeunload 和 unload 事件,需用 pagehide 替代。

二、事件触发场景差异

  1. Android

    • beforeunload:仅在 页面刷新 时触发,关闭 Tab 或浏览器不触发 。
    • 关闭操作需依赖 visibilitychange(切后台)或 pagehide(关闭 Tab)。
  2. iOS

    • 所有关闭操作(关闭 Tab、刷新、跳转)仅触发 pagehide 。
    • 微信浏览器中,左上角关闭按钮也通过 pagehide 监听 。

三、推荐兼容方案:多事件联合监听

结合 beforeunloadpagehidevisibilitychange 事件,并通过标志位避免重复执行:

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 + pagehidepagehide
关闭 Tabpagehidepagehide(iOS 14+)
切后台/退出浏览器visibilitychangevisibilitychange(仅切后台)
微信内关闭visibilitychangepagehide

关键结论

  • Android:组合使用 beforeunload + pagehide + visibilitychange
  • iOS仅依赖 pagehide,配合 sendBeacon 上报数据。
  • 微信浏览器:iOS 用 pagehide,Android 用 visibilitychange 78。

通过多事件联合监听 + sendBeacon,可覆盖 95% 以上的关闭场景,剩余极端情况(如 iOS 强制杀进程)无法捕获需业务降级处理。