多个onbeforeunload()和onunload()事件

5
我收到一位客户的奇怪问题,他们使用我们的代码,其中包含onbeforeunload()来触发对话框,但他们同时也在包含另一家公司的代码,该代码也绑定了这个事件处理程序。
两者是否可能同时执行?
我一直在阅读这本书:http://oreilly.com/catalog/9780596101992《JavaScript权威指南第5版》,试图更好地了解浏览器内部和Javascript堆栈中发生的事情,但它证明是相当困难的。
我从阅读该书中了解到,如果使用Level 2 API addEventListener() 绑定多个事件,有一些事件可能会同时被执行,但顺序将由浏览器决定。然而,没有提到onbeforeunload()事件,只有onunload()
这就引出了问题的第二部分。如果在onbeforeunload()中触发了事件,我是否正确地认为,除非它返回true,否则onunload()将永远不会被调用?
如果有人能够给出一些提示或向我提供一个关于如何将多个事件处理程序分配给同一个事件、或关于这两个事件的具体教程/指南,那将非常棒。
1个回答

8
有多个处理程序可以处理onbeforeunload事件,但它们将被依次调用而不是同时调用。实际上,Javascript在浏览器中是单线程的,因此不能真正意义上同时执行。如果任何onbeforeunload处理程序取消卸载,则不会调用任何onunload处理程序。您可以通过两种方式取消卸载(因为浏览器在这里有所不同):首先,将字符串分配给event对象的returnValue属性,然后将该字符串从函数中返回。详情请参见此处此处。(该字符串用作提示,允许用户决定是否取消卸载)。
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>
<style type='text/css'>
body {
    font-family: sans-serif;
}
</style>
<script type='text/javascript'>
window.onload = pageInit;
function pageInit() {
    hook(window, 'beforeunload', beforeUnload1);
    hook(window, 'beforeunload', beforeUnload2);
    hook(window, 'unload', unload1);
    hook(window, 'unload', unload2);
}

function beforeUnload1(event) {
    var s;

    event = event || window.event;
    s = "Message from beforeUnload1";
    event.returnValue = s
    return s;
}

function beforeUnload2(event) {
    var s;

    event = event || window.event;
    s = "Message from beforeUnload2";
    event.returnValue = s
    return s;
}

function unload1(event) {
    alert("Message from unload1");
}

function unload2(event) {
    alert("Message from unload2");
}

var hook = (function() {
    var d;

    function hookViaAttachEvent(obj, eventName, handler) {
        obj.attachEvent('on' + eventName, handler);
    }
    function hookViaAddEventListener(obj, eventName, handler) {
        obj.addEventListener(eventName, handler, false);
    }

    d = document.createElement('span');
    if (d.addEventListener) {
        return hookViaAddEventListener;
    }
    else if (d.attachEvent) {
        return hookViaAttachEvent;
    }
    throw "Neither attachEvent nor addEventListener found.";
})();
function hook(eventName, handler) {

}
</script>
</head>
<body></body>
</html>

在Chrome、IE和Firefox浏览器中,即使我确认可以离开页面,我也只会收到一个onbeforeunload处理程序的通知。我想这可能是为了防止某些讨厌的页面注册一堆处理程序并不断地纠缠用户留在页面上。

在(一个)询问后,如果我允许导航继续,我将收到两条卸载消息。


很棒的答案,谢谢!看起来我得绕过它,或者扩展我们的onbeforeunload()包装器以根据条件传递值。 - David Yell
我遇到了多个unload监听器的类似问题 - 只有一个会被触发...但只有当我在其中一个unload事件处理程序中没有警报调用时才会出现。非常奇怪。我正在考虑发布一个新的问题,除非这里可能有一个简单的解释? - Ash

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