我的目标是在浏览器标签关闭时删除用户Cookie。
有可能吗?我可以处理浏览器选项卡关闭事件而不刷新案例吗?
如果我使用anchors.right
或beforeunload
事件,在用户刷新页面时触发了功能,我不想要这个,我想在关闭标签时运行。
我如何在Angular中执行此操作?
答案 0 :(得分:12)
不幸的是,这不是一个简单的问题需要解决。但这是可以完成的。下面的答案是从许多不同的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.clientY
或event.clientX
以确定点击的内容以触发事件。
function doUnload(){
if (window.event.clientX < 0 && window.event.clientY < 0){
alert("Window closed");
}
else{
alert("Window refreshed");
}
}
Y轴无法正常工作,因为重新加载或标签/窗口关闭按钮的点击次数为负,而使用键盘快捷键重新加载时为正(例如F5,Ctrl-R,... )和窗口关闭(例如Alt-F4)。由于不同的浏览器具有不同的按钮放置,因此X轴无用。但是,如果您受到限制,那么通过一系列if-elses运行事件坐标可能是您最好的选择。请注意,这当然不可靠。
参与解决方案
(摘自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,此时您知道它来自较旧的会话,删除它并可选择提供一个新的设置在客户端上。
答案 1 :(得分:6)
$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
});
关于我们是否能够以万无一失的方式做到这一点,这是一个充分的争论。但技术上并不是很多事情可以在这里完成,因为你拥有的时间相当少,如果客户在你的行动完成之前关闭它,你就会陷入困境,而你完全怜悯客户。别忘了注入$ window。我建议不要依赖它。
javascript detect browser close tab/close browser
<强>更新强>
我正在研究这个问题以及一些建议。除了以上选项之外,处理此类情况的最佳方法是创建没有活动超时的会话,可能需要25-30分钟。将所有需要销毁的cookie转换为超时会话。或者,您可以设置cookie到期,但随后cookie将保留在浏览器中,直到下次登录。不到25-30分钟的会话不活动是不完全可靠的,因为如果客户端不使用浏览器10-15分钟就可以退出。我甚至尝试过基于链接(&lt; a
&gt;)或(&lt; submit
&gt;)或(keypress
)事件的捕获事件。问题是它能很好地处理页面刷新。但它不会消除客户端在删除cookie之前关闭浏览器或浏览器选项卡的问题。这是您在用例中必须考虑的事情,并且由于无法控制而强行权衡。最好将设计依赖于更好的架构而不是后来面对上述问题。
答案 2 :(得分:3)
也许此链接可以帮助您http://eureka.ykyuen.info/2011/02/22/jquery-javascript-capture-the-browser-or-tab-closed-event/
答案 3 :(得分:1)
我知道问这个问题已经有一段时间了,但我想我也会提供答案。我发现在不丢失cookie的情况下重新加载页面,并在窗口或标签关闭时删除cookie的最佳方法是使用ng-keydown来观看F5 Keypress(KeyCode 116)。
<强> HTML 强>
<body ng-controller="exitController" ng-keydown="isRefresh($event)">
<强> CONTROLLER 强>
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();
}
};
}]);
答案 4 :(得分:1)
我刚刚实施了一个(相对)简单的解决方案,上面没有提到。
HTML:
<div
(window:beforeunload)="doBeforeUnload()"
(window:unload)="doUnload()"
>
... your code here ...
</div>
TS:
doBeforeUnload() {
if (document.visibilityState === 'hidden') {
this.tabWasClosed = true;
}
return false;
}
doUnload() {
if (this.tabWasClosed) {
... perform logout action ...
}
}
我发现 beforeunload
和 unload
事件的逻辑是:
document.visibilityState
的值:
卸载前 | 卸载 | |
---|---|---|
标签关闭 | '隐藏' | '隐藏' |
标签已刷新 | '可见' | '隐藏' |
因此您可以将可见性状态与 beforeunload 事件一起使用来区分用户是刷新还是关闭了选项卡。我使用了一些额外的 localStorage
元素来检查注销状态,但这对于 5 年后遇到此问题的任何人来说可能都不需要。
MDN 上关于 document.visibilityState
的更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState
答案 5 :(得分:0)
如果您的目标是在浏览器关闭时删除Cookie,请不要设置过期时间。 浏览器关闭时会删除没有过期的Cookie。
您真的永远不需要知道用户是否关闭了他们的浏览器。我相信有其他方法可以实现你想要做的任何事情。
底线:
如果访问者不在您的页面上,那么用户使用浏览器或计算机进行的操作实际上与您无关。因此,如果没有来自用户的某种选择,例如浏览器扩展/插件,检测浏览器关闭可能永远不会实现。