No more than code.
监听页面关闭
| 监听页面关闭的方法
涉及场景:浮窗/左上角关闭/物理法返回键/右滑/切换应用/回到桌面
终极方案:同时使用 visibilitychange 和 pagehide。
mounted(){
window.addEventListener('pagehide', (e) => this.test1()); // 用于兼容 IOS 关闭页面
document.addEventListener('visibilitychange', (e) => this.test2()); // 浮窗/切换应用等隐藏页面
}
destroyed() {
window.removeEventListener('pagehide', e => this.test1())
document.removeEventListener('visibilitychange', e => this.test2())
},
methods: {
test1(){ // pagehide
if(IOS){
navigator.sendBeacon("/common/IP/getIP");
}
},
test2(){ // visibilitychange
// 用户息屏、或者切到后台运行 (离开页面)
if (document.visibilityState === 'hidden') {
navigator.sendBeacon("/common/IP/getIP");
}
}
},
遇到的坑:
- 监听 beforeunload PC 中有效(且可异步请求),微信中无效。
beforeunload & unload
beforeunload - 当浏览器窗口关闭或者刷新时,会触发 beforeunload 事件
unload - 当文档或一个子资源正在被卸载时, 触发 unload 事件,在 beforeunload 和 pagehide 事件后触发
unload 文档处于以下状态:
- 所有资源仍存在 (图片, iframe 等.)
- 对于终端用户所有资源均不可见
- 界面交互无效 (window.open, alert, confirm 等.)
- 错误不会停止卸载文档的过程
- 请注意 unload 事件也遵循文档树:父 iframe 会在子 iframe 卸载前卸载
- visibilitychange 在 android 中全场景生效,在 IOS 中关闭页面不生效,需同时使用 pagehide。pagehide[android/IOS] 仅限于关闭页面,对于切换应用/浮窗/回到桌面场景不生效。需注意 visibilitychange - document,pagehide - window
// 用户息屏、或者切到后台运行 (离开页面)
if (document.visibilityState === 'hidden') {
console.log('hidden');
}
// 用户打开或回到页面
if (document.visibilityState === 'visible') {
console.log('页面可见');
}
-
使用 axios 异步请求接口,由于页面卸载会导致请求发送取消或者发送失败。所以需要将请求改为同步。 将 xhr 请求改为同步,虽然能够完成发送数据,但存在以下两个问题:
- 部分浏览器已经不支持同步的 XMLHttpRequest 对象了(即 open()方法的第三个参数为 false);
- xhr 请求改为同步后,会阻塞页面的卸载和跳转,导致下一个页面导航加载的时机变晚,用户体验较差。
为了解决这个问题,浏览器引入了 Navigator.sendBeacon()方法。这个方法还是异步发出请求,但是请求与当前页面脱钩,作为浏览器的任务,因此可以保证会把数据发出去,不拖延卸载流程。