angularjs 如何在Angular中处理浏览器选项卡关闭事件?只关闭,不刷新

pod7payv  于 2022-10-31  发布在  Angular
关注(0)|答案(7)|浏览(250)

我的目标是在浏览器选项卡关闭时删除用户cookie。
可以吗?我可以在不刷新的情况下处理浏览器选项卡关闭事件吗?
如果我使用beforeunloadunload事件,函数在用户刷新页面时触发,我不希望这样,我只希望在关闭选项卡时运行。
如何在Angular中执行此操作?

tcbh2hod

tcbh2hod1#

不幸的是,这不是一个简单的问题,但它可以解决。下面的答案是从许多不同的SO答案中合并而来的。

**简单部分:**知道窗口正在被销毁。您可以使用onunload事件句柄来检测此情况。
棘手的部分:

检测它是刷新、链接跟随还是所需的窗口关闭事件。删除链接跟随和表单提交非常简单:

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

“穷人的解决方案"
正在检查event.clientYevent.clientX,以确定单击了什么触发了事件。

function doUnload(){
 if (window.event.clientX < 0 && window.event.clientY < 0){
   alert("Window closed");
 }
 else{
   alert("Window refreshed");
 }
}

Y轴不起作用,因为点击重新加载或选项卡/窗口关闭按钮时Y轴为负值,而使用键盘快捷键重新加载时Y轴为正值(例如,F5、Ctrl-R...)和窗口关闭(例如Alt-F4)。X轴没有用,因为不同的浏览器有不同的按钮位置。但是,如果您受到限制,那么通过一系列if-else运行事件坐标可能是最好的选择。

涉及的解决方案

(摘自Julien Kronegg)使用HTML5的本地存储和客户端/服务器 AJAX 通信。这种方法仅限于支持HTML5本地存储的浏览器。
在页面上,将onunload添加到窗口的以下处理程序中

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
}

然后将onloadon主体添加到以下处理程序

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

在服务器上,将断开连接请求收集到一个列表中,并设置一个定时器线程,该线程定期检查该列表(我每隔20秒使用一次).一旦断开连接请求超时(即5秒已过),断开用户与服务器的连接。如果在此期间接收到断开连接请求取消,则从列表中删除相应的断开连接请求,以便用户不会断开连接。
如果你想区分标签页/窗口关闭事件和跟随的链接或提交的表单,这种方法也适用。你只需要把这两个事件处理程序放在每个包含链接和表单的页面上,以及每个链接/表单登录页面上。

结束语(双关语):

由于您希望在窗口关闭时删除cookie,我假设这是为了防止它们在将来的会话中被使用。如果这是正确的假设,上面描述的方法将很好地工作。您将无效的cookie保留在服务器上(一旦客户端断开连接),当客户端创建新的会话时,JS会默认将cookie发送过来,此时您知道它来自较旧的会话,请将其删除,并选择性地提供一个要在客户端上设置的新会话。

uelo1irk

uelo1irk2#

$window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";
  console.log("closing the tab so do your small interval actions here like cookie removal etc but you cannot stop customer from closing");
  (e || window.event).returnValue = confirmationMessage; //Gecko + IE
  return confirmationMessage;                            //Webkit, Safari, Chrome
});

这是很有争议的,我们是否可以这样做或不傻瓜证明的方式。但技术上不是很多事情可以在这里做,因为你有时间是相当少,如果客户关闭它之前,你的行动完成,你有麻烦,你是在客户的怜悯完全。不要忘记注入$窗口。我建议不要依赖它。
javascript detect browser close tab/close browser

**更新:**我研究了这个问题沿着给出了一些建议。除了上面的选项,处理这种情况的最好方法是创建无活动超时时间为25-30分钟的会话。将所有需要销毁的cookie转换为有超时时间的会话。或者,您可以设置cookie过期时间,但cookie会一直保留在浏览器中,直到下次登录。会话无活动时间少于25-30分钟并不完全可靠,因为如果客户端10-15分钟不使用浏览器,您可能会被注销。我甚至尝试了从链接(< a >)或(< submit >)或(keypress)的事件。问题是它很好地处理页面刷新。但它并没有消除客户端在您的cookie被删除之前关闭浏览器或浏览器选项卡的问题。这是您必须在您的用例中考虑的问题,由于无法控制它,因此必须进行权衡。最好是根据其依赖性将设计更改为更好的体系结构,而不是在以后面对所提到的问题。

aoyhnmkz

aoyhnmkz3#

也许这个链接会帮助你

5us2dqdw

5us2dqdw4#

我刚刚实现了一个(相对)简单的解决方案,上面没有介绍。
于飞:

<div
  (window:beforeunload)="doBeforeUnload()"
  (window:unload)="doUnload()"
>
  ... your code here ...
</div>

技术支持:

doBeforeUnload() {
    if (document.visibilityState === 'hidden') {
      this.tabWasClosed = true;
    }

    return false;
  }

  doUnload() {
    if (this.tabWasClosed) {
      ... perform logout action ...
    }
  }

我发现的beforeunloadunload事件的逻辑是:
document.visibilityState的值:
| | 卸载前|卸载|
| - -|- -|- -|
| 选项卡已关闭|'隐藏'|'隐藏'|
| 选项卡已刷新|'可见'|'隐藏'|
因此,您可以使用visibilityState和beforeunload事件来区分用户是刷新了还是关闭了选项卡。我使用了一些额外的localStorage元素来检查注销状态,但对于5年后遇到此问题的任何人来说,可能都不需要这样做。
有关MDN上document.visibilityState的更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState

cwtwac6a

cwtwac6a5#

如果您的目标是在浏览器关闭时删除Cookie,请不要设置过期。没有过期的Cookie将在浏览器关闭时删除。
你真的不需要知道用户是否关闭了他们的浏览器。我相信有其他的方法来完成你想做的事情。

  • 底线:*
  • 如果访问者不再访问您的页面,那么用户在浏览器或计算机上做什么就与您无关。因此,如果用户不选择使用某种类型的浏览器扩展/插件,则检测浏览器关闭可能永远不会实现。*
c0vxltue

c0vxltue6#

我知道这个问题已经有一段时间没有被问到了,但是我想我也应该给出我的答案。我发现的在不丢失cookie的情况下重新加载页面,以及在窗口或标签页关闭时删除cookie的最好方法是使用ng-keydown来监视F5按键(键码116)。

HTML格式

<body ng-controller="exitController" ng-keydown="isRefresh($event)">

控制器

yourApp.controller('exitController', ['$rootScope', '$scope', '$window', '$cookies', function($rootScope, $scope, $window, $cookies) {
//set refresh to false to start out, it will become true only when we hit the refresh page
$scope.refresh = false;

//This is where we'll actually clear our cookies in the event of a window close
$scope.clearCookies = function() {
    $cookies.remove('sessionData');
    $cookies.remove('ss-id');
    $cookies.remove('ss-pid');
};

//When the user types any key, it will be assessed.
$scope.isRefresh = function(e) {
    var keyCode = e.keyCode; //find the key that was just pressed
    if(keyCode === 116) { //if the key that was pressed is F5, then we know it was a refresh
        $scope.refresh = true;
    }
}

//event that handles all refresh requests
window.onbeforeunload = function (e) {
    if (!$scope.refresh) { //as long as the trigger for the refresh wasnt initiated by F5, we remove the cookies
        $scope.clearCookies();
    }
};

}]);

yrdbyhpb

yrdbyhpb7#

参考编号:https://www.techiediaries.com/angular-leave-browser-beforeunload-event/
使用窗口的HostListener的最佳方法是:在应用程序组件或Tab键关闭事件的目标组件中执行beforeunload

@HostListener('window:beforeunload')
  onBeforeUnload() {
    return false;
}

相关问题