在刷新和关闭浏览器操作之间进行标识

时间:2009-02-20 10:06:23

标签: javascript browser

当我们刷新页面(F5或浏览器中的图标)时,它将首先显示 触发ONUNLOAD事件。当我们关闭浏览器时(右上方的图标上的X),它会 触发ONUNLOAD事件。 现在,当触发ONUNLOAD事件时,无法区分刷新页面或关闭浏览器。  如果您有任何解决方案,请给我。

13 个答案:

答案 0 :(得分:42)

有一个解决方案。

我希望在关闭选项卡或浏览器窗口时断开服务器上的用户连接,但是在重新加载页面时不要断开连接(您可能希望区分重新加载/关闭事件以用于其他目的,但您可以从我的解决方案中受益) 。基于HTML5的本地存储和客户端/服务器AJAX通信,我最终得到了以下过程:

    在您的网页上
  1. ,将onunload添加到window以下处理程序(伪javascript):

    function myUnload(event) {
        if (window.localStorage) {
            // flag the page as being unloading
            window.localStorage['myUnloadEventFlag']=new Date().getTime();
        }
    
        // notify the server that we want to disconnect the user in a few seconds (I used 5 seconds)
        askServerToDisconnectUserInAFewSeconds(); // synchronous AJAX call
    }
    
  2. 在您的网页上
  3. ,在onload上添加body到以下处理程序(pseudo-javascript):

    function myLoad(event) {
        if (window.localStorage) {
            var t0 = Number(window.localStorage['myUnloadEventFlag']);
            if (isNaN(t0)) t0=0;
            var t1=new Date().getTime();
            var duration=t1-t0;
            if (duration<10*1000) {
                // less than 10 seconds since the previous Unload event => it's a browser reload (so cancel the disconnection request)
                askServerToCancelDisconnectionRequest(); // asynchronous AJAX call
            } else {
                // last unload event was for a tab/window close => do whatever you want (I do nothing here)
            }
        }
    } 
    
  4. 在服务器上,收集列表中的断开连接请求,并设置一个定时器线程,定期检查列表(我每隔20秒使用一次)。一旦断开请求超时(即5秒消失),断开用户与服务器的连接。如果在此期间收到断开请求取消,则从列表中删除相应的断开连接请求,以便不断开用户。

  5. 如果要区分选项卡/窗口关闭事件和后续链接或提交的表单,此方法也适用。您只需要在包含链接和表单的每个页面上以及每个链接/表单登录页面上放置两个事件处理程序。

    请注意,我使用unload事件代替beforeUnload事件,以便正确管理指向附件的链接:当用户点击指向附件的链接(例如PDF文件)时,{调度{1}}事件,然后引发打开/保存弹出窗口,仅此而已(浏览器不会更改显示的页面,也不会调度beforeUnload事件)。如果我使用unload事件(就像我之前做过的那样),那么当没有页面更改时,我会检测到页面更改。

    此方法仅限于支持HTML5本地存储的浏览器,因此您可能会使用旧版浏览器(如MSIE7)的特定方法。

    基于beforeUnload的其他方法不可靠,因为当单击重新加载或选项卡/窗口关闭按钮时此值为负,而当使用键盘快捷键重新加载时为正(例如F5,Ctrl-R, ...)和窗口关闭(例如Alt-F4)。依靠事件X的位置也不可靠,因为按钮没有放在每个浏览器的相同位置(例如左边的关闭按钮)。

答案 1 :(得分:6)

不幸的是,正如此处的一些答案所示,检查事件的clientY / pageY值并不是确定unload事件是否被触发的可靠方法由于用户关闭页面。

单击浏览器的关闭按钮时clientY / pageY为负的原因是因为关闭按钮位于文档顶部上方(即像素0上方),但重新加载也是如此按钮意味着点击重新加载按钮也会导致clientY / pageY的值为负值。

沿着检查事件的x坐标的路径也是有问题的,因为浏览器关闭按钮并不总是在窗口的右侧(例如,它在OS X的左侧)并且因为窗口可以通过关闭其标签或键盘来关闭。

答案 2 :(得分:2)

不幸的是,目前尚无建议或可靠的方法。

答案 3 :(得分:1)

今天我遇到了同样的问题,并找到了我想与您分享的可能解决方案。

在考虑什么可以帮助辨别刷新和关闭时,我想到了cookie。我记得在没有明确到期日期的情况下设置cookie,使其仅适用于当前会话。在浏览器关闭之前,当前会话显然有效。这不包括关闭选项卡,但我的问题是关于用户身份验证,我不想仅为关闭选项卡而注销用户(我认为这与ASP.NET的ASPXAUTH cookie的方法相同)。

所以,当用户登录并在页面加载时检查它时,我在document.cookies集合中放了一个简单的cookie:如果cookie仍然存在,那么它是一个刷新或重新打开的选项卡,并保留用户数据,如果cookie当前会话已过期,因此用户数据已清除(与显式注销相同)。

希望这种方法对其他人有用!

答案 4 :(得分:1)

也许有人还在寻找答案...

您可以使用 SessionStorage !当页面重新加载但关闭时,未清除 SessionStorage。因此,基本上,您可以在加载页面时设置键/值对,但是在此之前,您需要检查键/值对是否存在。如果确实存在,则表示页面已重新加载;如果不存在,则意味着用户是首次打开页面或在新标签页中打开了页面。

if (sessionStorage.getItem('reloaded') != null) {
    console.log('page was reloaded');
} else {
    console.log('page was not reloaded');
}

sessionStorage.setItem('reloaded', 'yes');

这样,您可以doStuff()处理onunload事件(用户离开页面),如果设置了键/值对(用户重新加载页面),则otherStuff()。 >

答案 5 :(得分:0)

使用window.onbeforeunload事件使案例离开页面,但它将包括刷新或锚标签....使用相同的验证标志,该过程的一个示例是URL检查(初始URL =当前URL)或F5使用keycode进行刷新检查,如果是锚标签,则使用bind()

注意*如果是Chrome,Keycode可能会导致问题。

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>

<style type='text/css'>
body {
    font-family: sans-serif;
}
</style>
<script src="jquery-1.9.1.js" type='text/javascript'></script>
<script type='text/javascript'>
var valid=false;
function wireUpEvents() {

if(valid){
alert("Page Refreshed or Redirected");
}else{

window.onbeforeunload = askWhetherToClose;

}
function askWhetherToClose(event) {

if(!valid){

    var msg;

    msg = "You're leaving the page, do you really want to?";
    event = event || window.event;
    event.returnValue = msg;
    return msg;
}}
$(document).bind('keypress', function(e) { 
 if (e.keyCode == 116){ 

 // or you can insert some code to check page refresh
 valid = true; 

//wireUpEvents();
 } 
 }); 
 $("a").bind("click", function() {
//To check redirection using Anchor tags  
 valid = true; 
 //wireUpEvents();
 }); 
 }
$(document).ready(function() { 
 wireUpEvents(); 

 });
</script>
</head>
<body>
<p>Close the browser window, or navigate to <a href="http://stackoverflow.com">StackOverflow</a></p>
</body>
</html>

答案 6 :(得分:0)

它是可行的解决方案

export class BootstrapComponent implements OnInit {

  validNavigation = 0;

  constructor(
    private auth: AuthenticationService
  ) { }

  ngOnInit() {
    const self = this;
    self.registerDOMEvents();
  }

  registerDOMEvents() {
    const self = this;
    window.addEventListener('unload', () => {
      if (self.validNavigation === 0) {
        self.endSession();
      }
    });
    document.addEventListener('keydown', (e) => {
      const key = e.which || e.keyCode;
      if (key === 116) {
        self.validNavigation = 1;
      }
    });
  }

  endSession() {
    const self = this;
    self.auth.clearStorage();
  }
}

答案 7 :(得分:0)

贷记到https://www.anandkanatt.com/how-do-i-detect-browser-window-closed-refreshed/#comment-15892。我通过使用开瓶器本身进行了一些简化。在Chrome版本78.0.3887.7中进行了测试。

您可以尝试以下方法:

  • 添加refresh-close-detector.html文件。这是示例代码:
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Processing...</title>
</head>
<body>

<script>
  if (this.opener) {
    // the opener was refreshed, do something if you want
  } else {
    // the opener was closed, do something if you want
  }

  // you may want to close the pop up
  this.close()
</script>
</body>
</html>
  • 在您要识别刷新和关闭浏览器操作之间的页面中,添加要卸载的事件监听器:
window.addEventListener('unload', () => {
  open('refresh-close-detector.html', '', 'width=100,height=100');
})

答案 8 :(得分:0)

这是一个巨大的黑客,有一些限制,但在大多数实际情况下都可以使用。

因此,如果您只需要在用户使用ctrl + rcmd + r快捷方式时可以使用的功能,则可以跟踪{{1}当重新加载/关闭时您需要执行的操作被按下时,按}。

只需创建rkeydown事件侦听器即可切换keyup变量。

rDown

然后,您有了“ onunload”事件侦听器,其中的侦听器函数具有一条let rDown = false; window.addEventListener("keydown", event => { if (event.key == 'r') rDown = true; }) window.addEventListener("keyup", event => { if (event.key == 'r') rDown = false; }) 语句,用于检查if是否为rDown

true

答案 9 :(得分:-1)

我刚尝试了这个,它解决了这个问题: 创建一个sessionStorage对象,当用户关闭浏览器时,该对象将被销毁。我们可以检查sessionStorage对象以查找用户是否已关闭浏览器或刷新页面(sessionStorage对象在页面刷新时不会被销毁)。

答案 10 :(得分:-1)

--- 1 week ago ---
msg
msg
msg
msg
msg
----- today -----
msg 
msg 
msg
msg

使用if(window)确定是关闭还是仅重新加载。为我工作。

答案 11 :(得分:-2)

我早期的解决方案在IE中为我工作。对于除IE以外的浏览器,window.event将是未定义的,因为与其他浏览器不同,IE中的“事件”是全局定义的。在其他浏览器的情况下,您需要提供事件作为参数。另外,clientX没有为firefox定义,我们应该使用pageX。

尝试类似这样的东西....应该适用于IE和Firefox这个......

<html>
<body>
<script type="text/javascript">

window.onunload = function(e) {
// Firefox || IE
e = e || window.event;

var y = e.pageY || e.clientY;

if(y < 0)  alert("Window closed");
else alert("Window refreshed");

}
</script>
</body>
</html>

答案 12 :(得分:-8)

<html>
<body onunload="doUnload()">
<script>
   function doUnload(){
     if (window.event.clientX < 0 && window.event.clientY < 0){
       alert("Window closed");
     }
     else{
       alert("Window refreshed");
     }
   }
</script>
</body>
</html>