Vue.js结合Quasar框架如何检测标签页/浏览器关闭触发登出且避免刷新触发
区分页面关闭和刷新触发登出的实现方案
问题原因
你现在用的beforeunload事件本身无法区分「关闭标签/浏览器」和「刷新页面」两种行为,两种操作都会触发该事件,所以才会出现刷新也执行登出的问题。
核心实现思路
浏览器没有原生提供直接区分两种操作的API,我们可以结合两个特性间接实现:
sessionStorage仅在当前标签页会话生效,页面刷新时内容保留,关闭标签/浏览器后自动清空navigator.sendBeaconAPI专门用于页面卸载前的请求发送,不会被浏览器主动中断
方案1:会话存储轻量方案(无后端额外适配)
如果你的鉴权凭证(如JWT Token)是存储在sessionStorage中,其实不需要监听beforeunload事件:
- 关闭标签/浏览器时
sessionStorage自动清空,用户下次打开页面时无有效凭证,自动进入登出状态 - 刷新页面时
sessionStorage内容保留,用户登录状态不受影响
方案2:主动调用登出接口方案(需要后端简单适配)
如果必须主动调用后端登出接口销毁会话,可以用以下逻辑实现:
- 页面卸载时先发送登出请求
- 页面加载时判断如果是刷新操作,立即发送会话续期请求,后端收到续期请求后取消对应会话的登出操作
代码示例
// 替换为你的实际鉴权凭证 const USER_TOKEN = 'your_auth_token'; // 页面加载时执行 window.addEventListener('load', () => { // 判断当前是否为刷新操作 const navEntry = performance.getEntriesByType('navigation')[0]; const isRefresh = navEntry?.type === 'reload'; if (isRefresh) { // 刷新场景调用会话续期接口,通知后端不要销毁当前会话 fetch('/api/session/renew', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token: USER_TOKEN }) }); } }); // 监听页面卸载事件 window.addEventListener('beforeunload', () => { // 组装登出参数 const logoutData = new FormData(); logoutData.append('token', USER_TOKEN); // 必须用sendBeacon发送请求,避免浏览器中断普通AJAX请求 navigator.sendBeacon('/api/logout', logoutData); });
注意事项
- 不要在
beforeunload中使用同步XMLHttpRequest或者普通fetch请求,页面卸载时浏览器大概率会直接中断这类请求,导致登出失败 - 后端需要增加简单的逻辑:如果同一个token在1s内先后收到登出和续期请求,不执行登出操作即可
内容的提问来源于stack exchange,提问作者Shubham Sankpal
相关产品推荐
相关产品推荐

