为什么onbeforeunload事件没有触发

25

我在Chrome、FireFox和Safari上尝试了这段代码,但是onbeforeunload却没有触发。我还尝试了onunload,但也没有成功。

以下是我正在进行实验的代码:

<!doctype html>
<html lang="en">
<head>
  <title> Output to a Page </title>
  <meta charset="utf-8">
  <script> 
    window.onload = init;
    window.onclick = clk;
    window.onbeforeunload = closing;
    function clk() {
        window.alert("Ouch !!");
    }
    function closing() {
        console.log("function alrt WORKS !!!!");
        window.alert("closing now.....");
    }
    function init() {  
      var output = "";
      for (var mms = 5; mms > 0; mms--) {
        if (mms >= 3) {
            output += "Still lots of M&amp;Ms left, so eat more!<br>";
        } else {
            output += "Getting low on M&amp;Ms, take it easy!<br>";
        }
      }
      output += "All out of M&amp;Ms";
      var e = document.getElementById("output");
      e.innerHTML = output;
    }

  </script>
</head>
<body>  
  <p id="output"></p>
</body>
</html>
4个回答

62

onbeforeunload是Web开发人员世界中最大的误解之一 :D

1)它拒绝调用所有阻塞本地函数(alert、prompt、confirm)。这从用户的角度来看是显而易见的。

2)根据MDN的说法,它应该由“addEventListener”进行注册。(MDN

3)只有在用户与网站有任何交互时才会触发它。没有任何交互(甚至是单击任何地方),事件onbeforeunload将不会被触发。

4)此事件的目的是秘密保存用户提交的表单数据(或其他操作记录等)。它不是用于阻止刷新网站!

因此,没有办法(因为这将毫无意义)显示个性化信息。

唯一有意义的是,在重新加载时隐藏提示窗口并保存先前保存的数据。

5)如果要隐藏提示窗口,只需不为event.returnValue字段设置任何值。

此示例在刷新期间卸载站点(在控制台上编写文本“UNLOAD:1”)而不显示窗口提示。

window.addEventListener("beforeunload", function(event) {
  console.log("UNLOAD:1");
  //event.preventDefault();
  //event.returnValue = null; //"Any text"; //true; //false;
  //return null; //"Any text"; //true; //false;
});

这个例子在刷新时通过窗口提示卸载网站(在控制台上打印文本“UNLOAD:1”)。

window.addEventListener("beforeunload", function(event) {
  console.log("UNLOAD:1");
  //event.preventDefault();
  event.returnValue = null; //"Any text"; //true; //false;
  //return null; //"Any text"; //true; //false;
});

您可以使用事件.returnValue的任何值(如右侧所列)。这只是一种编码风格问题。

无论是event.preventDefault还是return都不会影响此事件(因此在您的代码中,可以省略那些已注释的行)。

测试过Chrome、Edge、Firefox、Opera(经2019年9月23日验证)。希望对您有所帮助。

[编辑:]

为了避免通过屏幕意外滑动/拖动重新加载移动应用程序(例如谷歌地图、图像和任何其他稳定内容),可以使用此CSS技巧:

    body {
       overscroll-behavior-y: contain !important;
    }

应用程序将安全地防止重新加载。

值得考虑为用户提供另一种可能性(例如某个按钮)以便在需要时重新加载。


15
对我来说,最有价值的信息是那个奇怪的第三点。谢谢! - user1039663
5
3)这是非常有价值的信息。我想知道为什么我尝试了成千上万次,它从未起作用。谢谢。 - Kai Lehmann
2
@user1039663,这与最近实施的音频播放规则类似。用户必须与页面进行“交互”,才能使页面输出媒体声音。 - Hiro
这是我见过的关于Onbeforeunload的完美答案。谢谢! - Hassan Serhan
1
是的,我也犯了同样的错误,我在没有做任何操作的情况下关闭了浏览器,所以 onbeforeunload 没有起作用。 - undefined
显示剩余2条评论

26

onbeforeunload事件由于安全原因无法被取消,但是如果 onbeforeunload 事件的事件处理函数返回一个字符串值,这个文本将显示在确认对话框中,用户可以确认是否留在当前页面。

请注意,使用addEventListenerattachEvent方法不能注册onbeforeunload事件监听器(只有Safari和Google Chrome支持)。为了实现跨浏览器解决方案,请在HTML中注册事件处理程序(使用元素的onbeforeunload属性)或使用window对象的onbeforeunload内联事件属性。详见下面的示例:

示例:

在HTML中:

<ELEMENT onbeforeunload="handler">

在JavaScript中:

object.onbeforeunload = handler;                        
object.addEventListener ("beforeunload", handler, useCapture);

触发 onbeforeunload 事件的行为包括:

  1. 在浏览器中直接导航到另一页或通过链接导航。
  2. 关闭当前的浏览器窗口或标签页。
  3. 重新加载当前页面。
  4. 通过 JavaScript 中的 location 对象操纵当前加载的页面 URL。
  5. 调用 window.navigate 方法。
  6. 调用 window.opendocument.open 方法,在同一窗口打开文档。

尝试修改您的代码,像这样:

window.onbeforeunload = closing;
/* other code here */

var closing = function () {
        console.log("function alrt WORKS !!!!");
        window.alert("closing now.....");
       }

或者直接将代码放置于您的 body 标签中:

<body onbeforeunload="alert('function alrt WORKS !!!!')">

请查看此处此处以获取更多详细信息。


1
目前这是我能够实现完全跨浏览器支持onbeforeunload事件的唯一方法(Firefox在某些情况下不会触发它)。感谢这个很棒的答案! - user3351605

3

我遇到了一个问题,无论是beforeunload还是onunload都不能在用户关闭浏览器时执行一个ajax调用。事实上,这些方法都没有起作用。JavaScript方法位于body标签内部,这实际上是问题所在。当我将JavaScript方法移动到Head标签中时,问题神奇地解决了。


你能分享一个代码示例吗?我不太确定你的意思。 - Josh Powlison

1
针对在某些浏览器(例如我的情况中的Safari)遇到此问题的人,经过一些研究后,我意识到这是由于浏览器工作方式导致的。 此帖子有更详细的解释。
基本上,我所做的是使用替代方法,即onpagehide,到目前为止,我已经测试了所有浏览器都可以正常运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接