javascript window.onbeforeunload 可能会触发多次

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4126820/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 10:27:12  来源:igfitidea点击:

window.onbeforeunload may fire multiple times

javascriptjqueryonbeforeunload

提问by David Murdoch

Just because you don't see use for a feature doesn't mean it isn't useful.

仅仅因为您没有看到某个功能的用途并不意味着它没有用。

The Stack Exchange network, GMail, Grooveshark, Yahoo! Mail, and Hotmail use the onbeforeunload prompt to prevent/warn users that they are leaving a page after they have begun editing something. Oh yah, nearly every single desktop programthat accepts saveable user-input data utilizes this prompt-user-before-leaving UX pattern.

Stack Exchange 网络、GMail、Grooveshark、Yahoo! 邮件和 Hotmail 使用 onbeforeunload 提示来防止/警告用户他们在开始编辑某些内容后离开页面。哦,是的,几乎每个接受可保存用户输入数据的桌面程序都使用这种提示用户离开前的 UX 模式。



I have a function which behaves similarly to this one:

我有一个功能类似于这个功能:

window.onbeforeunload = function(){
    // only prompt if the flag has been set... 
    if(promptBeforeLeaving === true){
        return "Are you sure you want to leave this page?";
    }
}

When a user attempts navigates away from the page the browser presents them with the option to leave or stay on the page. If the user selects the "Leave this page option" and then they quickly click on a link again before the page unloads completely the dialog fires again.

当用户尝试离开页面时,浏览器会向他们显示离开或留在页面上的选项。如果用户选择“离开此页面选项”,然后他们在页面完全卸载之前再次快速单击链接,对话框将再次触发。

Are there any foolproof solutions to this problem?

这个问题有没有万无一失的解决方案?



Note: The following NOT the solution:

注意:以下不是解决方案:

var alreadyPrompted = false;
window.onbeforeunload = function(){
    // only prompt if the flag has been set... 
    if(promptBeforeLeaving === true && alreadyPrompted === false){
        alreadyPrompted = true;
        return "Are you sure you want to leave this page?";
    }
}

because the user might select the "Stay on the page" option which would cause future onbeforeunloads to stop working.

因为用户可能会选择“留在页面上”选项,这会导致 futureonbeforeunload停止工作。

采纳答案by Josiah Ruddell

I think you could accomplish this with a timer (setInterval) that starts in the onbeforeunloadcallback. Javascript execution will be paused while the confirm dialog is up, then if the user cancels out the timed function could reset the alreadyPromptedvariable back to false, and clear the interval.

我认为您可以使用setIntervalonbeforeunload回调中启动的计时器 ( )来完成此操作。Javascript 执行将在确认对话框启动时暂停,然后如果用户取消计时功能可以将alreadyPrompted变量重置回 false,并清除间隔。

Just an idea.

只是一个想法。

Ok I did a quick test based on your comment.

好的,我根据您的评论进行了快速测试。

<span id="counter">0</span>
window.onbeforeunload = function () {
   setInterval(function () { $('#counter').html(++counter); }, 1);
   return "are you sure?";
}
window.onunload = function () { alert($('#counter').html()) };

In between the two callbacks #counternever got higher than 2 (ms). It seems like using these two callbacks in conjunction gives you what you need.

在两次回调之间#counter从未超过 2 (ms)。结合使用这两个回调似乎可以满足您的需求。

EDIT - answer to comment:

编辑 - 回答评论:

Close. This is what i was thinking

关闭。这就是我的想法

var promptBeforeLeaving = true,
    alreadPrompted = false,
    timeoutID = 0,
    reset = function () {
        alreadPrompted = false;
        timeoutID = 0;
    };

window.onbeforeunload = function () {
    if (promptBeforeLeaving && !alreadPrompted) {
        alreadPrompted = true;
        timeoutID = setTimeout(reset, 100);
        return "Changes have been made to this page.";
    }
};

window.onunload = function () {
    clearTimeout(timeoutID);
};

回答by kofifus

I have encapsulated the answers from above in an easy to use function:

我已经将上面的答案封装在一个易于使用的函数中:

function registerUnload(msg, onunloadFunc) {
    var alreadPrompted = false,
        timeoutID = 0,
        reset = function() {
            alreadPrompted = false;
            timeoutID = 0;
        };

    if (msg || onunloadFunc) { // register
        window.onbeforeunload = function() {
            if (msg && !alreadPrompted) {
                alreadPrompted = true;
                timeoutID = setTimeout(reset, 100);
                return msg;
            }
        };

        window.onunload = function() {
            clearTimeout(timeoutID);
            if (onunloadFunc) onunloadFunc();
        };
    } else { // unregister
        window.onbeforeunload = null;
        window.onunload = null;
    }
}

To register use:

注册使用:

registerUnload("Leaving page", function() { /* unload work */ });

To unregister use:

取消注册使用:

registerUnload();

Hope this helps ..

希望这可以帮助 ..