如何优化仅关闭标签页时登出而非刷新时登出的实现?
问题:关闭标签页时自动登出的实现优化
我用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,提问作者黃柏瑋
相关产品推荐
相关产品推荐

