背景:在做数据埋点时遇到了 “上报页面停留时间” 的需求。
开发历程:
1.刚看到这个需求时,心想,这不是很简单嘛,现在页面初始化后获取一下时间戳然后直接在componentWillUnmount把时间差进行上报不就行了嘛。于是一顿操作猛如虎,开发完毕。
结果:在切换页面时,数据成功上报了。
2.但问题果然并没有那么简单,我发现如果用户直接刷新页面或者直接关闭页面时,componentWillUnmount里的代码是不会执行的,思考一番后,我决定在页面初始化后去监听页面关闭事件,于是一顿操作猛如虎,在页面初始化后,我给window添加了‘beforeunload’的事件监听:
window.addEventListener('beforeunload', ()=>{
// 你的一系列操作...
})
结果:在PC端,用户直接刷新页面或者直接关闭页面时,数据成功上报了。
3.但问题果然并没有那么简单,当用户在移动端直接刷新页面或者直接关闭页面时,发现数据并没有上报成功,google一下,发现beforeunload并不支持移动端,于是,google一下后,我决定换成监听‘pagehide’事件:
window.addEventListener('pagehide', ()=>{
// 你的一系列操作...
})
结果:在pc和移动端,用户直接刷新页面或者直接关闭页面时,数据成功上报了。
4.但问题果然并没有那么简单,移动端****当用户最小化窗口或切换到另一个选项卡时,并不会触发‘pagehide’,于是又google一番后,我发现了Page Visibility API,我们可以通过监听visibilitychange事件并结合****document.visibilityState属性判断页面当前的可见性:
document.addEventListener('visibilitychange', ()=> {
if(document.visibilityState === 'hidden'){
//页面处于不可见状态
}else if(document.visibilityState === 'visible'){
//页面处于可见状态
}
});
结果:在页面不可见之前,数据成功上报了。
问题貌似得到了解决,但当中依然存在不少的坑:
1.在直接页面关闭或刷新页面时,使用异步上报的方式是不能成功的,需要使用同步上报(异步上报没有造成阻塞)
2.通过组合上面的方法可以应对大部分浏览器的兼容性问题,但并不能保证事件一定会触发,如,移动端safari在直接关闭浏览器或浏览器页面时不会触发‘pagehide’事件。
网友评论