检测用户何时离开网页的最佳方法?

IT技术 javascript
2021-01-29 14:36:06

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

onunloadJavaScript事件不起作用每次(HTTP请求花费的时间比需要的时间终止浏览器)。

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

6个回答

试试这个onbeforeunload事件:它在页面被卸载之前被触发。它还允许您询问用户是否真的想离开。查看演示onbeforeunload Demo

或者,您可以在他离开时发送Ajax请求。

另请注意,各种移动浏览器会忽略事件的结果(即,它们不要求用户确认)。Firefox 在 about:config 中有一个隐藏的偏好来做同样的事情。本质上,这意味着用户总是确认可以卸载文档。
2021-03-11 14:36:06
如果您跟踪表单是否更改并且仅在更改时进行提示,那么这对用户来说会很好 - 所以这并不烦人。
2021-03-12 14:36:06
请注意,此方法也会在用户刷新页面或提交表单时调用。
2021-03-23 14:36:06
@Andreas Petersson,我有同样的挑战,目的是放弃用户会话。我如何捕获输入的 url 以检查它是否属于该项目?
2021-04-05 14:36:06

Mozilla Developer Network 有一个很好的描述和onbeforeunload示例

如果您的页面脏了(即,如果用户输入了一些数据),如果您想在离开页面之前警告用户:

window.addEventListener('beforeunload', function(e) {
  var myPageIsDirty = ...; //you implement this logic...
  if(myPageIsDirty) {
    //following two lines will cause the browser to ask the user if they
    //want to leave. The text of this dialog is controlled by the browser.
    e.preventDefault(); //per the standard
    e.returnValue = ''; //required for Chrome
  }
  //else: user is allowed to leave without a warning dialog
});

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

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

缺点是,当然这是用户实际打算离开猜测,但在绝大多数情况下这是正确的。

我看起来像,我想向我的用户展示一些不引人注目的东西,在离开我的页面之前,我看起来像后退按钮上的悬停事件,因为我需要在用户点击返回之前触发该事件。我相信最好的方法是真正检测鼠标离开正文文档,并做一些逻辑来确定用户是否与页面交互。
2021-03-21 14:36:06

感谢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')
    )
  }
})
你的意思是在客户端代码的某个地方,需要有一个setInterval(() => fetch('/heartbeat'), 5000)?
2021-03-18 14:36:06
@DanDascalescu 正确。JS 代码向 /heartbeat 发出网络请求,Service Worker 拦截它。
2021-04-09 14:36:06

我知道这个问题已得到解答,但如果您只想在实际浏览器关闭时触发某些内容,而不仅仅是在页面加载发生时触发,您可以使用以下代码:

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

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

不会说我错了。我的示例在 IE 和 Chrome 中适用于我就好了。我的示例是针对用户单击 Web 浏览器上的 X(关闭)的场景。也许也不是最漂亮的方式,但它确实有效。
2021-03-19 14:36:06
window.event 对我来说是未定义的
2021-03-29 14:36:06
Merr Leader 的例子是错误的,window.event 应该只作为一个fallback,例如对于老版本的IE,其他情况下,e应该使用event参数(本例中变量): stackoverflow.com/questions/9813445/ …
2021-03-29 14:36:06
来自 MDN:This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. developer.mozilla.org/en-US/docs/Web/API/Window/event
2021-04-04 14:36:06