多个OnBeforeUnload事件

13

我正在编写一个作为插件使用的JS代码。该JS代码具有onbeforeunload事件。

我想得到建议,以使我的onbeforeunload事件不会覆盖现有的onbeforeunload事件(如果存在的话)。我能否将我的onbeforeunload事件附加到现有事件上?

谢谢。

8个回答

18

我感觉这个问题还没有得到完全回答,因为没有展示使用addEventListener的示例(但The MAZZTer指出了addEventListener的解决方案)。我的解决方案与Julian D.的解决方案相同,但不使用jQuery,只使用本机JavaScript。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Before Unload</title>
</head>
<body>
    <p>Test</p>

    <script>
      window.addEventListener('beforeunload', function (event) {
        console.log('handler 1')
        event.preventDefault()
        event.returnValue = ''
      });

      window.addEventListener('beforeunload', function (event) {
        console.log('handler 2')
      });
    </script>
</body>
</html>

在这个例子中,两个监听器都将被执行。如果有任何其他设置了beforeunload监听器,它不会覆盖它们。我们将得到以下输出(顺序不能保证):

handler 1
handler 2

而且,如果一个或多个事件监听器执行了event.preventDefault(); event.returnValue = '',那么会出现一个提示,询问用户是否真的想重新加载。

如果您正在编辑一个表单,同时通过ajax下载文件,不希望在任何这些操作中丢失数据,这时就可以使用此功能。每个操作都可以有一个监听器来防止页面重新加载。

const editingForm = function (event) {
  console.log('I am preventing losing form data')
  event.preventDefault()
  event.returnValue = ''
}

const preventDownload = function (event) {
  console.log('I am preventing a download')
  event.preventDefault()
  event.returnValue = ''
}

// Add listener when the download starts
window.addEventListener('beforeunload', preventDownload);
// Add listener when the form is being edited
window.addEventListener('beforeunload', editingForm);

// Remove listener when the download ends
window.removeEventListener('beforeunload', preventDownload);
// Remove listener when the form editing ends
window.removeEventListener('beforeunload', editingForm);

2
这必须被标记为答案,因为它没有外部库和全局钩子的干扰。 - simply good
这个解决方案比直接分配给window.onbeforeunload要好得多。我可以添加和删除任意数量的事件侦听器。 - justin
为什么你既要阻止默认行为又要设置 returnValue?你只需要其中一个就可以了。 - Sampson Crowley
1
我的问题的答案是,显然有50%的事件常青浏览器仍然不支持这个最明显的标准,直接返回字符串实际上是具有最高支持的方法。 - Sampson Crowley

15

只有在没有使用事件观察但直接附加 onbeforeunload 处理程序时才需要注意这一点(您不应该这样做)。如果是这样,请使用类似以下的内容来避免覆盖现有处理程序。

(function() {
    var existingHandler = window.onbeforeunload;
    window.onbeforeunload = function(event) {
        if (existingHandler) existingHandler(event);

        // your own handler code here
    }
})();

不幸的是,您无法防止其他(后续)脚本覆盖您的处理程序。但同样可以通过添加事件侦听器来解决此问题:

$(window).unload(function(event) {
    // your handler code here
});

第一部分我们在谈论'onbeforeunload',而第二部分关于事件监听器、钩子的'unload'是否也需要? - Jackie Degl'Innocenti
3
最好放弃你的第一个解决方案,只需使用window.addEventListener('beforeunload', () => {/事件处理/});,想用多少次就用多少次。 - simply good

3

我的想法:

var callbacks = [];
window.onbeforeunload = function() {
    while (callbacks.length) {
        var cb = callbacks.shift();
        typeof(cb)==="function" && cb();
    }
}

并且

callbacks.push(function() {
    console.log("callback");
});

2
如果您使用jQuery进行绑定,它将把绑定附加到现有列表中,因此无需担心。从jQuery文档on()方法中可以看到:

从jQuery 1.4开始,同一事件处理程序可以绑定到一个元素多次。

function greet(event) { alert("Hello "+event.data.name); }
$("button").on("beforeunload", { name: "Karl" }, greet);
$("button").on("beforeunload", { name: "Addy" }, greet); 

2

试试这个:

var f = window.onbeforeunload;
window.onbeforeunload = function () {
    f();
    /* New code or functions */
}

你可以多次修改这个函数,而不会失去其他功能。

0

您可以使用不同的JavaScript框架,如jQuery,或者您可能可以添加一个小的事件处理程序来完成此操作。例如,您有一个包含许多已添加函数的对象,然后在onbefore unload中运行这些已添加的函数。因此,当您想要将新函数添加到事件中时,您只需将其添加到您的对象中即可。

类似于这样:

var unloadMethods = [];
function addOnBeforeUnloadEvent(newEvent) { //new Event is a function
    unloadMethods[unloadMethods.length] = newEvent;
}

window.onbeforeunload = function() {
    for (var i=0; i<unloadMethods.length; i++) {
        if(typeof unloadMethods[i] === "function") {unloadMethods[i]();}
    }
}

0

0
我喜欢Marius的解决方案,但是在此基础上进行了改进,以满足变量f为null的情况,并返回链中任何函数返回的第一个字符串。
function eventBeforeUnload(nextFN){
    //some browsers do not support methods in eventAdd above to handle window.onbeforeunload
    //so this is a way of attaching more than one event listener by chaining the functions together 
    //The onbeforeunload expects a string as a return, and will pop its own dialog - this is browser behavior that can't
    //be overridden to prevent sites stopping you from leaving. Some browsers ignore this text and show their own message.
    var firstFN = window.onbeforeunload;
    window.onbeforeunload = function () {
        var x;
        if (firstFN) {
            //see if the first function returns something
            x = firstFN();
            //if it does, return that
            if (x) return x;
        }
        //return whatever is returned from the next function in the chain
        return nextFN();
    }
}

在你的代码中需要时将其用作这样。
eventBeforeUnload(myFunction);
//or
eventBeforeUnload(function(){if(whatever) return 'unsaved data';);

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