如何捕获浏览器窗口关闭事件?

How to capture the browser window close event?

提问人:khelll 提问时间:10/28/2009 最后编辑:kenorbkhelll 更新时间:8/25/2022 访问量:493261

问:

我想捕获浏览器窗口/选项卡关闭事件。 我用jQuery尝试了以下方法:

jQuery(window).bind(
    "beforeunload", 
    function() { 
        return confirm("Do you really want to close?") 
    }
)

但它也适用于表单提交,这不是我想要的。我想要一个仅在用户关闭窗口时触发的事件。

JavaScript jQuery 事件 浏览器

评论

0赞 Behnam Faghih 5/9/2023
如果您想非常精确,请查看此解决方案:stackoverflow.com/questions/76139970/...

答:

1赞 i_am_jorf 10/28/2009 #1

也许您可以处理 OnSubmit 并设置一个标志,稍后在 OnBeforeUnload 处理程序中签入该标志。

46赞 karim79 10/28/2009 #2

也许只是在表单的事件处理程序中取消绑定事件处理程序:beforeunloadsubmit

jQuery('form').submit(function() {
    jQuery(window).unbind("beforeunload");
    ...
});

评论

3赞 awe 4/12/2011
通过在表单标记定义中指定它来不使用 jQuery,这不是很容易吗?: '<form onsubmit=“window.onbeforeunload=null;”>
4赞 KajMagnus 9/17/2011
@awe但是你需要在每份表格中都包含它。(在某个网络应用程序中,我每页有很多表单)onsubmit=...
231赞 SLaks 10/28/2009 #3

每当用户出于任何原因离开您的页面时,都会触发该事件。beforeunload

例如,如果用户提交表单、单击链接、关闭窗口(或选项卡)或使用地址栏、搜索框或书签转到新页面,则会触发该按钮。

您可以使用以下代码排除表单提交和超链接(其他框架除外):

var inFormOrLink;
$('a').on('click', function() { inFormOrLink = true; });
$('form').on('submit', function() { inFormOrLink = true; });

$(window).on("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

对于早于 1.7 的 jQuery 版本,请尝试以下操作:

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

该方法不适用于事件,因此,如果添加新窗体,则还需要将处理程序绑定到该窗体。livesubmit

请注意,如果其他事件处理程序取消了提交或导航,则在稍后实际关闭窗口时,您将丢失确认提示。您可以通过在 和 事件中记录时间并检查是否在几秒钟后发生来解决这个问题。submitclickbeforeunload

评论

8赞 Venkat D. 8/27/2011
是的,工作很棒!较新版本的 jquery 支持 $('form').live('submit, function() { })。
6赞 Refael 10/22/2013
您的解决方案很好,但是在刷新的情况下如何取消事件?我只想要浏览器关闭时的事件,没有刷新的情况
0赞 tahagh 8/4/2014
浏览器似乎将beforeunload的返回值显示为确认对话框。所以我觉得这个答案比较准确:链接
3赞 Arti 8/13/2015
这是否使用 、 和更改浏览器 URL 处理页面刷新?Ctrl + rF5Ctrl + Shift + r
1赞 SLaks 12/27/2017
@Jonny:现在只是..on()
0赞 idrumgood 10/28/2009 #4

如果您的表单提交将它们带到另一个页面(正如我假设的那样,因此触发了 ),您可以尝试将表单提交更改为 ajax 调用。这样,他们在提交表单时不会离开您的页面,您可以根据需要使用绑定代码。beforeunloadbeforeunload

-7赞 Dilhan Jayathilaka 11/17/2011 #5

跟随对我有用;

 $(window).unload(function(event) {
    if(event.clientY < 0) {
        //do whatever you want when closing the window..
    }
 });

评论

8赞 Julien Kronegg 12/17/2012
如果单击浏览器关闭按钮或选项卡关闭按钮,则为负数。但是,当您使用键盘快捷键(F5、Ctrl-R)或使用键盘快捷键(例如 Alt-F4)关闭浏览器时,此值为正值。因此,您不能依赖事件位置来区分浏览器关闭事件和页面重新加载事件。event.clientY
0赞 Yoosaf Abdulla 4/14/2012 #6

我的问题:只有当提交(点击次数)为奇数时,才会触发“onbeforeunload”事件。我在 SO 中结合了来自类似线程的解决方案,以使我的解决方案正常工作。好吧,我的代码会说话。

<!--The definition of event and initializing the trigger flag--->


$(document).ready(function() {
  updatefgallowPrompt(true);
  window.onbeforeunload = WarnUser; 
}

function WarnUser() {
  var allowPrompt = getfgallowPrompt();
  if(allowPrompt) {
    saveIndexedDataAlert();
    return null;
  } else {
    updatefgallowPrompt(true);
    event.stopPropagation
  }
}

<!--The method responsible for deciding weather the unload event is triggered from submit or not--->
function saveIndexedDataAlert() {
  var allowPrompt = getfgallowPrompt();
  var lenIndexedDocs = parseInt($('#sortable3 > li').size()) + parseInt($('#sortable3 > ul').size());

  if(allowPrompt && $.trim(lenIndexedDocs) > 0) {
    event.returnValue = "Your message";
  } else {
    event.returnValue = "   ";
    updatefgallowPrompt(true);
  }
}

<!---Function responsible to reset the trigger flag---->
$(document).click(function(event) {  
  $('a').live('click', function() { updatefgallowPrompt(false); });
});

<!--getter and setter for the flag---->
function updatefgallowPrompt (allowPrompt){ //exit msg dfds
  $('body').data('allowPrompt', allowPrompt);   
}   

function getfgallowPrompt(){        
  return $('body').data('allowPrompt'); 
}
3赞 kapad 4/30/2012 #7

我使用了 Slaks 答案,但这并没有按原样工作,因为 onbeforeunload returnValue 被解析为字符串,然后显示在浏览器的确认框中。因此,显示值 true,如“true”。

只是使用返回工作。 这是我的代码

var preventUnloadPrompt;
var messageBeforeUnload = "my message here - Are you sure you want to leave this page?";
//var redirectAfterPrompt = "http://www.google.co.in";
$('a').live('click', function() { preventUnloadPrompt = true; });
$('form').live('submit', function() { preventUnloadPrompt = true; });
$(window).bind("beforeunload", function(e) { 
    var rval;
    if(preventUnloadPrompt) {
        return;
    } else {
        //location.replace(redirectAfterPrompt);
        return messageBeforeUnload;
    }
    return rval;
})
17赞 desm 9/25/2012 #8

对于跨浏览器解决方案(在 Chrome 21、IE9、FF15 中测试),请考虑使用以下代码,这是 Slaks 代码的略微调整版本:

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
}); 

请注意,从 Firefox 4 开始,不再显示“Do you really want to close?”消息。FF 只显示一条通用消息。请参阅 https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload 中的注释

评论

4赞 Sablefoste 2/1/2013
这个在浏览器上始终如一地工作。只是一个简短的说明;我将 和 语句都更新为 ,这适用于最新级别的 jQuery。谢谢!livebindon
4赞 PLT 5/14/2013 #9

对于适用于第三方控件(如 Telerik(例如:RadComboBox)和 DevExpress)的解决方案,这些控件出于各种原因使用定位标记,请考虑使用以下代码,该代码是 desm 代码的略微调整版本,具有更好的自定位定位定位标记选择器:

var inFormOrLink;
$('a[href]:not([target]), a[href][target=_self]').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
});

评论

1赞 LeonPierre 5/6/2015
这个答案是正确的,但对于那些在刷新浏览器时遇到此事件问题的人,请将 if 更改为以下代码:if (inFormOrLink !== undefined && !inFormOrLink)
0赞 Tom 7/11/2013 #10

从 jQuery 1.7 开始,不推荐使用 .live() 方法。使用 .on() 附加事件处理程序。旧版本jQuery的用户应优先使用.delegate()而不是.live()

$(window).bind("beforeunload", function() {
    return true || confirm("Do you really want to close?"); 
}); 

完成或链接

$(window).unbind();
-1赞 Brunno 12/27/2013 #11

只需验证...

function wopen_close(){
  var w = window.open($url, '_blank', 'width=600, height=400, scrollbars=no, status=no, resizable=no, screenx=0, screeny=0');
  w.onunload = function(){
    if (window.closed) {
       alert("window closed");
    }else{ 
       alert("just refreshed");
    }
  }
}

评论

0赞 Sergey P. aka azure 11/4/2016
这是行不通的。在 unload 事件触发的那一刻(顺便说一句,它是从文档触发的),window.closed === false;
19赞 Behnam 3/9/2014 #12
window.onbeforeunload = function () {
    return "Do you really want to close?";
};
1赞 Coding man 6/30/2015 #13
jQuery(window).bind("beforeunload", function (e) {
    var activeElementTagName = e.target.activeElement.tagName;
    if (activeElementTagName != "A" && activeElementTagName != "INPUT") {
        return "Do you really want to close?";
    }
})
1赞 Gary 12/10/2015 #14

不幸的是,无论是重新加载、新页面重定向还是浏览器关闭,都会触发该事件。另一种方法是捕获触发事件的 id,如果是表单,则不要触发任何函数,如果它不是表单的 id,则在页面关闭时执行您想执行的操作。我不确定这是否也可以直接实现,而且很乏味。

您可以在客户关闭选项卡之前做一些小事情。 JavaScript 检测浏览器关闭选项卡/关闭浏览器,但是如果您的操作列表很大并且选项卡在完成之前关闭,那么您就无能为力了。你可以尝试一下,但以我的经验,不要依赖它。

window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";
  /* Do you small action code here */
  (e || window.event).returnValue = confirmationMessage; //Gecko + IE
  return confirmationMessage;                            //Webkit, Safari, Chrome
});

https://developer.mozilla.org/en-US/docs/Web/Reference/Events/beforeunload?redirectlocale=en-US&redirectslug=DOM/Mozilla_event_reference/beforeunload

10赞 zurfyx 11/30/2016 #15

我的回答旨在提供简单的基准。

如何

请看@SLaks答案

$(window).on("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

浏览器需要多长时间才能最终关闭您的页面?

每当用户关闭页面(按钮或+)时,浏览器都会执行给定的代码,但不是无限期的。唯一的例外是确认框 (),它将等待用户的响应。xCTRLWbeforeunloadreturn 'Do you really want to close?

Chrome:2 秒。
Firefox:∞(或双击,或强制关闭) Edge:∞(或双击)

Explorer 11:0 秒。
Safari待办事项

我们用来测试这一点:

  • 具有请求日志的 Node.js Express 服务器
  • 以下简短的 HTML 文件

它的作用是在浏览器关闭其页面(同步)之前发送尽可能多的请求。

<html>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script>
    function request() {
        return $.ajax({
            type: "GET",
            url: "http://localhost:3030/" + Date.now(),
            async: true
        }).responseText;
    }
    window.onbeforeunload = () => {
        while (true) {
            request();
        }
        return null;
    }
    </script>
</body>
</html>

铬输出:

GET /1480451321041 404 0.389 ms - 32  
GET /1480451321052 404 0.219 ms - 32  
...  
GET /hello/1480451322998 404 0.328 ms - 32

1957ms ≈ 2 seconds // we assume it's 2 seconds since requests can take few milliseconds to be sent.
-1赞 Bhaskara Arani 12/6/2016 #16

也试试这个

window.onbeforeunload = function ()
{       
    if (pasteEditorChange) {
        var btn = confirm('Do You Want to Save the Changess?');
           if(btn === true ){
               SavetoEdit();//your function call
           }
           else{
                windowClose();//your function call
           }
    }  else { 
        windowClose();//your function call
    }
};
-2赞 Muhammad Arslan 4/18/2017 #17
var validNavigation = false;
            jQuery(document).ready(function () {

                wireUpEvents();
            });

            function endSession() {
                // Browser or broswer tab is closed
                // Do sth here ...
                alert("bye");
            }

            function wireUpEvents() {
                /*
                * For a list of events that triggers onbeforeunload on IE
                * check http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
                */
                window.onbeforeunload = function () {
                    debugger
                    if (!validNavigation) {
                        endSession();
                    }
                }

                // Attach the event keypress to exclude the F5 refresh
                $(document).bind('keypress', function (e) {
                    debugger
                    if (e.keyCode == 116) {
                        validNavigation = true;
                    }
                });

                // Attach the event click for all links in the page
                $("a").bind("click", function () {
                    debugger
                    validNavigation = true;
                });

                // Attach the event submit for all forms in the page
                $("form").bind("submit", function () {
                    debugger
                    validNavigation = true;
                });

                // Attach the event click for all inputs in the page
                $("input[type=submit]").bind("click", function () {
                    debugger
                    validNavigation = true;
                });

            }`enter code here`