检测用户是否离开网页的最佳方法是什么?

onunload JavaScript事件并不是每次都有效(HTTP请求所花费的时间比终止浏览器所需的时间长)。

创建一个可能会被当前的浏览器阻止。


当前回答

在需要执行一些异步代码的情况下(比如向服务器发送消息,说明用户现在没有关注您的页面),beforeunload事件将不会给异步代码运行时间。在异步的情况下,我发现能见度变化和mouseleave事件是最好的选择。当用户更改选项卡、隐藏浏览器或将courser移出窗口作用域时,这些事件将触发。

文档。addEventListener (mouseleave, e = > { //执行一些异步代码 }) 文档。addEventListener (visibilitychange, e = > { 如果文档。visbilitystate === 'visible') { //报告用户处于焦点中 }其他{ //报告用户不聚焦 } })

其他回答

多亏了Service Workers,在浏览器支持的情况下,完全在客户端实现类似于Adam的解决方案成为可能。只需绕过心跳请求:

// The delay should be longer than the heartbeat by a significant enough amount that there won't be false positives
const liveTimeoutDelay = 10000
let liveTimeout = null

global.self.addEventListener('fetch', event => {
  clearTimeout(liveTimeout)
  liveTimeout = setTimeout(() => {
    console.log('User left page')
    // handle page leave
  }, liveTimeoutDelay)
  // Forward any events except for hearbeat events
  if (event.request.url.endsWith('/heartbeat')) {
    event.respondWith(
      new global.Response('Still here')
    )
  }
})

这里有一个替代的解决方案-因为在大多数浏览器的导航控件(导航栏,选项卡等)位于页面内容区域的上方,你可以检测到鼠标指针通过顶部离开页面,并显示一个“离开前”对话框。它完全不引人注目,它允许你在用户实际执行离开操作之前与他们进行交互。

$(document).bind("mouseleave", function(e) {
    if (e.pageY - $(window).scrollTop() <= 1) {    
        $('#BeforeYouLeaveDiv').show();
    }
});

缺点是,这当然是一种猜测,用户真的想要离开,但在绝大多数情况下,这是正确的。

我知道这个问题已经被回答了,但如果你只想在实际浏览器关闭时触发一些东西,而不仅仅是在页面加载发生时,你可以使用以下代码:

window.onbeforeunload = function (e) {
        if ((window.event.clientY < 0)) {
            //window.localStorage.clear();
            //alert("Y coords: " + window.event.clientY)
        }
};

在我的例子中,我正在清除本地存储并用鼠标y坐标提醒用户,只有当浏览器关闭时,这将在程序内的所有页面加载中被忽略。

你能做的就是在页面加载时打开一个WebSocket连接,可以选择通过WebSocket发送数据来标识当前用户,然后在服务器上检查连接何时关闭。

在需要执行一些异步代码的情况下(比如向服务器发送消息,说明用户现在没有关注您的页面),beforeunload事件将不会给异步代码运行时间。在异步的情况下,我发现能见度变化和mouseleave事件是最好的选择。当用户更改选项卡、隐藏浏览器或将courser移出窗口作用域时,这些事件将触发。

文档。addEventListener (mouseleave, e = > { //执行一些异步代码 }) 文档。addEventListener (visibilitychange, e = > { 如果文档。visbilitystate === 'visible') { //报告用户处于焦点中 }其他{ //报告用户不聚焦 } })