如何实现用户离开项目网页时触发登出(排除站内跳转)
解决站内跳转触发beforeunload登出的问题
我明白你的痛点——beforeunload事件太"灵敏"了,不管是跳站内页面、刷新还是关窗口都会触发,完全不符合你只想在跳外部或关窗口时登出的需求。下面给你一套可行的解决方案,分步骤来:
核心思路
我们需要给页面加一个"状态标记",区分用户当前的操作是站内跳转还是外部跳转/关闭窗口/刷新,只有后者才触发登出逻辑。
具体实现步骤
1. 添加全局状态标记
在所有非index.html的页面脚本开头,定义一个全局变量用来标记是否是站内跳转:
// 全局标记:是否为站内跳转 let isInternalNavigation = false;
2. 监听所有站内链接的点击事件
给页面上所有<a>标签添加点击监听,判断目标链接是否是站内地址,如果是就把标记设为true:
document.addEventListener('click', function(e) { // 找到点击的a标签(考虑嵌套元素的情况) const targetLink = e.target.closest('a'); if (!targetLink) return; const linkHref = targetLink.getAttribute('href'); if (!linkHref) return; // 判断是否为站内链接:相对路径、当前域名的绝对路径都算 const isInternal = linkHref.startsWith('/') || linkHref.startsWith('./') || linkHref.startsWith('../') || linkHref.includes(window.location.host); if (isInternal) { isInternalNavigation = true; // 跳转后重置标记,避免影响后续操作 setTimeout(() => { isInternalNavigation = false; }, 100); } });
3. 修改beforeunload事件逻辑
在原来的beforeunload监听里,先检查全局标记,只有非站内跳转时才执行登出:
$(window).on("beforeunload", function() { // 仅当不是站内跳转时,才触发登出 if (!isInternalNavigation) { logoutAccount(false); } });
4. 额外处理页面刷新的情况(可选)
如果你希望用户刷新页面时也保持登录状态(而不是触发登出),可以再加一层判断:
// 页面加载时标记是否为刷新操作 window.addEventListener('load', function() { const navEntry = performance.getEntriesByType("navigation")[0]; // 标记当前是否是刷新页面 if (navEntry && navEntry.type === 'reload') { sessionStorage.setItem('isPageRefresh', 'true'); } else { sessionStorage.removeItem('isPageRefresh'); } }); // 修改beforeunload逻辑,排除刷新场景 $(window).on("beforeunload", function() { const isRefresh = sessionStorage.getItem('isPageRefresh') === 'true'; // 非站内跳转 + 非刷新,才触发登出 if (!isInternalNavigation && !isRefresh) { logoutAccount(false); } });
5. 处理JS主动跳转的场景(可选)
如果你的页面里有用JS触发的跳转(比如window.location.href = 'home.html'),记得手动设置标记:
// 封装一个站内跳转的函数 function goToInternalPage(url) { isInternalNavigation = true; window.location.href = url; setTimeout(() => { isInternalNavigation = false; }, 100); } // 使用示例: // goToInternalPage('statistics.html');
最终的登出相关代码整合
把上面的代码整合后,你的非index.html页面脚本里的登出部分会变成这样:
let isInternalNavigation = false; // 监听站内链接点击 document.addEventListener('click', function(e) { const targetLink = e.target.closest('a'); if (!targetLink) return; const linkHref = targetLink.getAttribute('href'); if (!linkHref) return; const isInternal = linkHref.startsWith('/') || linkHref.startsWith('./') || linkHref.startsWith('../') || linkHref.includes(window.location.host); if (isInternal) { isInternalNavigation = true; setTimeout(() => { isInternalNavigation = false; }, 100); } }); // 页面加载标记刷新状态 window.addEventListener('load', function() { const navEntry = performance.getEntriesByType("navigation")[0]; if (navEntry && navEntry.type === 'reload') { sessionStorage.setItem('isPageRefresh', 'true'); } else { sessionStorage.removeItem('isPageRefresh'); } }); function logoutAccount(redirect) { if(localStorage['loggedAccount']){ var account=JSON.parse(localStorage['loggedAccount']); var logoutRequest=new XMLHttpRequest(); logoutRequest.open('GET',url+"/logout/"+account.id,false); logoutRequest.send(null); localStorage.removeItem('loggedAccount'); if(redirect){ window.location.replace("index.html"); } }else{ if(redirect){ window.location.replace("index.html"); } } } document.getElementById("logoutButton").addEventListener("click",function () { logoutAccount(true); }); $(window).on("beforeunload", function() { const isRefresh = sessionStorage.getItem('isPageRefresh') === 'true'; if (!isInternalNavigation && !isRefresh) { logoutAccount(false); } });
这样修改后,用户在站内页面间跳转、刷新页面都不会触发登出,只有跳转到外部链接或者关闭窗口时才会执行登出逻辑,完美符合你的需求~
内容的提问来源于stack exchange,提问作者Mr.D
相关产品推荐
相关产品推荐

