
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 & unload
beforeunload - 当浏览器窗口关闭或者刷新时,会触发 beforeunload 事件
unload - 当文档或一个子资源正在被卸载时, 触发 unload 事件,在 beforeunload 和 pagehide 事件后触发
unload 文档处于以下状态:
// 用户息屏、或者切到后台运行 (离开页面)
if (document.visibilityState === 'hidden') {
console.log('hidden');
}
// 用户打开或回到页面
if (document.visibilityState === 'visible') {
console.log('页面可见');
}
使用 axios 异步请求接口,由于页面卸载会导致请求发送取消或者发送失败。所以需要将请求改为同步。 将 xhr 请求改为同步,虽然能够完成发送数据,但存在以下两个问题:
为了解决这个问题,浏览器引入了 Navigator.sendBeacon()方法。这个方法还是异步发出请求,但是请求与当前页面脱钩,作为浏览器的任务,因此可以保证会把数据发出去,不拖延卸载流程。