window.onbeforeunload 可能会触发多次

发布于 2024-10-01 08:59:16 字数 986 浏览 5 评论 0原文

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

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


我有一个与此功能类似的功能:

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

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

对于这个问题有什么万无一失的解决方案吗?


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

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?";
    }
}

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

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 program that accepts saveable user-input data utilizes this prompt-user-before-leaving UX pattern.


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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情绪操控生活 2024-10-08 08:59:16

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

只是一个想法。

好的,我根据您的评论做了一个快速测试。

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

在两个回调之间,#counter 从未高于 2(毫秒)。看起来结合使用这两个回调可以满足您的需要。

编辑 - 评论答案:

关闭。这就是我的想法

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);
};

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

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 #counter never got higher than 2 (ms). It seems like using these two callbacks in conjunction gives you what you need.

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);
};
别低头,皇冠会掉 2024-10-08 08:59:16

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

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;
    }
}

注册使用:

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

取消注册使用:

registerUnload();

希望这会有所帮助..

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 ..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文