关闭页面时使用jquery的beforeunload事件(而不是离开页面)?

91
如何在用户实际尝试关闭页面(单击浏览器窗口或选项卡上的X按钮)时显示“您确定要离开该页面吗?”而不是当他尝试离开页面时(单击另一个链接)显示消息?
我的客户想要在用户尝试关闭页面时出现一条消息“您确定要离开该页面吗?您的购物车中仍有商品。”
不幸的是,$(window).bind('beforeunload')只有在用户关闭页面时才能触发。 jQuery:
function checkCart() { 
  $.ajax({
    url : 'index.php?route=module/cart/check',
    type : 'POST',
    dataType : 'json',
    success : function (result) {
       if (result) {
        $(window).bind('beforeunload', function(){
          return 'leave?';
        });
       }
    }
  })
}

https://dev59.com/B3XZa4cB1Zd3GeqPAvwR#18395961 - Voonic
1
你无法通过编程来区分浏览器关闭还是用户离开了你的页面。 - user229044
@Cris 发生了什么错误? - Padmanathan J
您的消息包含一些代码,表明正在运行 Ajax 操作。我们需要考虑其中的一些吗?(因为除了这些代码,您没有明确提到它) - Cyril N.
如果您正在使用多标签浏览器,您无法判断窗口是否关闭或导航到另一个URL,这时候并没有什么区别。但是,如果您使用哈希导航(例如http://yourdomain.com/#path=/index/news&id=1),您可以在导航时通过JavaScript进行管理。 - alphakevin
你的代码片段会导致多个绑定,每次ajax调用都会增加;尝试在绑定新事件之前解除先前的事件绑定。 - Vishal
7个回答

154

你可以通过使用 JQuery 来实现这一点。

例如,

<a href="your URL" id="navigate"> click here </a>

您的JQuery将会是:

$(document).ready(function(){

    $('a').on('mousedown', stopNavigate);

    $('a').on('mouseleave', function () {
           $(window).on('beforeunload', function(){
                  return 'Are you sure you want to leave?';
           });
    });
});

function stopNavigate(){    
    $(window).off('beforeunload');
}

获得离开留言提醒的方法是:

$(window).on('beforeunload', function(){
      return 'Are you sure you want to leave?';
});

$(window).on('unload', function(){

         logout();

});

这个解决方案适用于所有浏览器,我已经测试过了。


2
这是一个不错的解决方案(你可能也应该观察onsubmit),但它无法处理浏览器的“后退”和“前进”按钮。我预计这个问题没有理想的解决方案。 - noseratio - open to work
@Bit_hunter 使用 confirm() 对话框。 - RozzA
1
这个 $(window).on('unload', function() 在Safari浏览器中没有被执行。 - Aarohi Kulkarni
1
如果浏览器因操作系统关闭而关闭,beforeunload会触发吗? - techie_28
5
由于Chrome和Firefox希望防止欺诈行为,所以您现在无法提供自定义消息(在关闭页面时):https://developers.google.com/web/updates/2016/04/chrome-51-deprecations#remove_custom_messages_in_onbeforeunload_dialogs - Adam
显示剩余2条评论

17

尝试将JavaScript嵌入您的Ajax中

window.onbeforeunload = function(){
  return 'Are you sure you want to leave?';
};

参考 链接

示例 2:

document.getElementsByClassName('eStore_buy_now_button')[0].onclick = function(){
    window.btn_clicked = true;
};
window.onbeforeunload = function(){
    if(!window.btn_clicked){
        return 'You must click "Buy Now" to make payment and finish your order. If you leave now your order will be canceled.';
    }
};

每当用户离开页面时,此代码将提示用户,直到用户点击按钮。

演示: http://jsfiddle.net/DerekL/GSWbB/show/


14

功劳应归于这里: 如何检测窗口 onbeforeunload 触发时是否单击了链接?

基本上,该解决方案添加了一个侦听器来检测链接或窗口是否导致卸载事件触发。

var link_was_clicked = false;
document.addEventListener("click", function(e) {
   if (e.target.nodeName.toLowerCase() === 'a') {
      link_was_clicked = true;
   }
}, true);

window.onbeforeunload = function(e) {
    if(link_was_clicked) {
        return;
    }
    return confirm('Are you sure?');
}

3

如此所示https://dev59.com/73I-5IYBdhLWcg3w3crS#1632004,您可以通过“筛选”导致离开此页面的内容来实现它。

如评论中所提到的,在其他问题中,以下是代码的新版本,其中还包括您在问题中进行的ajax请求:

var canExit = true;

// For every function that will call an ajax query, you need to set the var "canExit" to false, then set it to false once the ajax is finished.

function checkCart() {
  canExit = false;
  $.ajax({
    url : 'index.php?route=module/cart/check',
    type : 'POST',
    dataType : 'json',
    success : function (result) {
       if (result) {
        canExit = true;
       }
    }
  })
}

$(document).on('click', 'a', function() {canExit = true;}); // can exit if it's a link
$(window).on('beforeunload', function() {
    if (canExit) return null; // null will allow exit without a question
    // Else, just return the message you want to display
    return "Do you really want to close?";
});

重要提示:不应该定义全局变量(这里是canExit),这只是为了简化版本。

请注意,你无法完全覆盖确认消息(至少在Chrome中)。你返回的消息只会被添加到Chrome给出的消息前面。原因在于:如何覆盖OnBeforeUnload对话框并用自己的替换它?


3
自jQuery 1.7起,.live 已过时。应使用 $(document).on('click', 'a', ...) 代替它。通常情况下,.on 是优先使用的方式,对于 .bind,应使用 $('form').on('submit', ...) - t.niese
我相当确定这个答案不再跨浏览器了。有人测试过吗? - A. Wolff
如上所述,我只是复制/粘贴了代码。我将使用最新版本编辑答案。 - Cyril N.
谢谢,但不幸的是,在我关闭标签时确认框没有弹出。 - Cris
我犯了一个大错误(将文档事件从beforeunload改为click)。 - Cyril N.

0

这里有一个函数,你可以在代码的任何地方使用它

function setProcessing(isProcessing) {
  $(window).on('beforeunload', function(event) {
    if (isProcessing) {
      event.preventDefault();
      return '';
    }
  });
}

只需设置 setProcessing(true) 或 setProcessing(false)


0

尝试这个,通过ajax加载数据并通过返回语句显示。

<script type="text/javascript">
function closeWindow(){

    var Data = $.ajax({
        type : "POST",
        url : "file.txt",  //loading a simple text file for sample.
        cache : false,
        global : false,
        async : false,
        success : function(data) {
            return data;
        }

    }).responseText;


    return "Are you sure you want to leave the page? You still have "+Data+" items in your shopping cart";
}

window.onbeforeunload = closeWindow;
</script>

2
每次用户在您的网站上点击链接时,让他们等待同步 AJAX 调用的响应并不是一个好主意。 - mattalxndr

-2

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