You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化仅关闭标签页时登出而非刷新时登出的实现?

问题:关闭标签页时自动登出的实现优化

我用sessionStorage实现了仅在关闭标签页时登出的功能,但体验不佳。代码如下:

if (sessionStorage.getItem('reloaded') != null) {
console.log('page was reloaded');
} else {
console.log("page was closed");
fetch('logout.php', {
    method: 'POST', // Use POST for sensitive actions like logout
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded', // Content type
    },
  
})
.then(response => {
    if (response.ok) {
        console.log('Logged out successfully');
        window.location.replace("http://localhost/foodblog/index.php");
    } else {
        console.log('Logout failed');
    }
})
.catch(error => {
    console.error('Error during logout:', error);
});


}


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

这个方案会在页面加载时触发跳转,观感很差。我也试过用unload事件监听器:

window.addEventListener('unload', function () {

navigator.sendBeacon('logout.php');
});

这个方案运行正常,但unload事件已被废弃,请问有什么改进方法?

对应的logout.php代码:

<?php
session_start();

if(isset($_SESSION["user_id"])){
  unset($_SESSION["user_id"]);
}

if(isset($_SESSION["username"])){
   unset($_SESSION["username"]);
}
session_destroy();
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time() - 3600, '/');
}
header("Location: index.php");
exit();
?>

解决方案

1. 使用 visibilitychange 事件

该事件会在页面可见性变化时触发(如标签页切换、窗口最小化、页面关闭),可通过文档可见状态判断是否触发登出:

document.addEventListener('visibilitychange', function() {
  if (document.visibilityState === 'hidden') {
    navigator.sendBeacon('logout.php');
  }
});

注意:切换到其他标签页也会触发该事件,若仅需在关闭标签页时登出,可结合pagehide事件进一步判断。

2. 使用 pagehide 事件

pagehide是unload的官方替代方案,专门用于页面卸载场景,浏览器支持度良好:

window.addEventListener('pagehide', function(event) {
  // event.persisted为false时,说明页面即将被销毁(而非缓存或刷新)
  if (!event.persisted) {
    navigator.sendBeacon('logout.php');
  }
});

3. 优化logout.php逻辑

当前logout.php中的跳转逻辑在sendBeacon请求中无效(页面已进入卸载流程),可移除跳转,仅返回状态即可:

<?php
session_start();

if(isset($_SESSION["user_id"])){
  unset($_SESSION["user_id"]);
}

if(isset($_SESSION["username"])){
   unset($_SESSION["username"]);
}
session_destroy();
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time() - 3600, '/');
}
// 返回成功状态,前端按需处理跳转
echo json_encode(['status' => 'success']);
exit();
?>

4. 多事件结合的可靠方案

为覆盖更多场景,可同时监听visibilitychange和pagehide,并避免重复触发:

let hasLoggedOut = false;

function triggerLogout() {
  if (!hasLoggedOut) {
    navigator.sendBeacon('logout.php');
    hasLoggedOut = true;
  }
}

document.addEventListener('visibilitychange', function() {
  if (document.visibilityState === 'hidden') {
    triggerLogout();
  }
});

window.addEventListener('pagehide', function(event) {
  if (!event.persisted) {
    triggerLogout();
  }
});

该方案既规避了unload的废弃问题,又能可靠触发关闭标签页时的登出操作,同时解决了页面加载时跳转的观感问题。

内容的提问来源于stack exchange,提问作者黃柏瑋

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 11:36:11