Skip to content

Latest commit

 

History

History
137 lines (96 loc) · 4.8 KB

浏览器关闭事件分析.md

File metadata and controls

137 lines (96 loc) · 4.8 KB
title date
浏览器关闭事件分析
2017/02/21 14:47:11

0、导言

很多时候,我们可能会遇到这样一类需求:

  1. 浏览器关闭时,弹出一个新页面
  2. 浏览器关闭时,发送统计信息(如页面浏览时长)
  3. 浏览器关闭时,让用户二次确认

这个时候,我们就需要考虑如何判断浏览器关闭,如何阻止浏览器关闭,如何在浏览器关闭时,还是执行特定操作。

1、浏览器关闭与刷新判断

对于关闭与刷新判断,一般有以下几种做法:

首先基础都是通过监听 onbeforeunloadonunload 等相关事件。

然后判断刷新与关闭:

  1. 判断鼠标坐标
  2. 判断键盘操作
  3. 判断事件间隔时长

其中,1和2一般是合起来使用。但也并不保险。关闭和刷新的快捷操作是可以自定义的。而且实现逻辑复杂。

在这里,我就重点来测试线通过判断事件间隔的方式来处理关闭与刷新的判断。

我们编写了如下测试代码

window.onbeforeunload = function () {
  console.log('onbeforeunload', Date.now());
  debugger
};

window.onunload = function(){
  console.log('onunload', Date.now());
  debugger
}

分别在浏览器上刷新和关闭,得到如下结果:

浏览器 关闭/刷新 onbeforeunload onunload
Chrome 关闭 [x] [x]
Chrome 刷新 [x] [x]
Firefox 关闭 [x] [x]
Firefox 刷洗 [x] [x]
Edge 关闭 [x] []
Edge 刷新 [x] [x]
IE11 关闭 [x] [x]
IE11 刷新 [x] [x]

Edge关闭时,unload是否触发,还并不太确定(不太好验证)。

接下来,我们来验证两个时间的触发时间,测试代码如下:

window.onbeforeunload = function (evt) {
  console.log('onbeforeunload', Date.now());
  if (navigator.sendBeacon) {
    navigator.sendBeacon('http://localhost:9999/?t=onbeforeunload', 'onbeforeunload');
  }
  window.start = Date.now();
};

window.onunload = function () {
  console.log('onunload', Date.now());
  if (navigator.sendBeacon) {
    navigator.sendBeacon(`http://localhost:9999/?t=onunload&ts=${Date.now() - window.start}`, 'onunload');
  }
  window.open('http://10.16.85.170:8000/');
}

通过 navigator.sendBeacon 将间隔时间发送到后台进行查看。遗憾的是,IE和Edge并不支持该方法。

测试得出如下表格:

浏览器 关闭/刷新 onbeforeunload onunload 时间间隔
Chrome52 关闭 [x] [x] < 5ms
Chrome52 刷新 [x] [x] > 20ms
Firefox46 关闭 [x] [x] > 200ms
Firefox46 刷洗 [x] [x] 10~100ms
Edge13 关闭 [x] [] N/A
Edge13 刷新 [x] [x] < 5ms
IE11 关闭 [x] [x] > 10ms
IE11 刷新 [x] [x] < 5ms

根据这个表格,然后在按照自己的需要,就可以选择一个分割点来判断是刷新还是关闭。

当前未发现100%能判断清楚的方法,以上请酌情使用。

2、阻止浏览器关闭

有一些场景,要求在浏览器关闭的时候,再次弹出一个确认框,那这个又应该如何实现呢?

关闭时询问,是一个比较标准化的处理了,只需要我们对 unbeforeunload 事件的 event 参数设置返回值,即可达到再次确认的效果。实现代码如下:

window.addEventListener('beforeunload', function(evt){
  evt.returnValue =  '您确定要离开了么?';
}, false);

注意:火狐为了避免不必要的弹窗,如果页面没有交互,是不会进行二次确认的,通过不会显示returnValue给用户。相关链接: https://developer.mozilla.org/zh-TW/docs/Web/API/WindowEventHandlers/onbeforeunload

3、浏览器关闭/刷新时发送统计数据

很多时候,我们想在浏览器关闭/刷新时发送一些统计数据,之前的话,我们可以采用如下一些做法:

  1. onbeforeunload 中使用同步Ajax
  2. 发送Ajax,然后使用死循环,阻塞一个该事件。

这个功能作为一个比较大众化的需求,W3C中也有了一个针对性的草案,那就是浏览器对象的 sendBeacon 方法。

函数签名如下:

navigator.sendBeacon(url, data);

有了这个方法,我们就可以在合适的地方(诸如onbeforeunload)发送我们的统计数据,日志数据等等。

注意:该方法还是草案阶段,当前IE和EDGE暂不可用。

4、相关资料

  1. MDN WindowEventHandlers.onbeforeunload
  2. MDN Navigator.sendBeacon()