1、需求前提
项目使用Vue + SpringBoot搭建的前后端分离项目,后端存储用户登录信息和Token。现在的需求是,多端只可以有一个用户登录,当一个用户关闭浏览器或者关闭标签页时,向后端发送请求删除该用户的登录信息,以此来解决用户及时下线的目的。
2、解决方案
直接上代码
mounted() {
window.addEventListener('beforeunload', (e) => this.beforeUnload(e));
// 添加关闭浏览器触发器
window.addEventListener('unload', this.logout);
},
methods: {
beforeUnload(e) {
e = e || window.event;
if (e) {
e.returnValue = '关闭提示';
}
return '关闭提示';
},
// 关闭浏览器标签触发
logout() {
fetch('/login/loginOut?userId=admin'), {
method: 'GET',
headers: {'Content-Type': 'application/json'},
keepalive: true
});
},
重点1:
window.addEventListener('beforeunload', (e) => this.beforeUnload(e));
// 点击 <button>离开</button> 按钮时触发
window.addEventListener('unload', this.logout);
重点2:
// 关闭浏览器标签触发
logout() {
fetch('/login/loginOut?userId=admin'), {
method: 'GET',
mode: 'no-cors', // 重点一定要注意
headers: {'Content-Type': 'application/json'},
keepalive: true
});
},
可能你也观察到了,我使用了fetch请求,那是因为axios异步请求在这里不起作用!(PS: 浪费了好多时间。)
同时,fetch请求最大支持** 64KB**的请求体,所以注意传参的载荷。
同时如果是前后端分离项目,一定加上跨域设置 no-cors。否则部署线上则会出现跨域异常。
3、实际项目中的源码
mounted() {
// 添加关闭浏览器触发器
window.addEventListener('beforeunload', (e) => this.beforeUnload(e));
window.addEventListener('unload', this.logout);
}
methods: {
beforeUnload(e) {
e = e || window.event;
if (e) {
e.returnValue = '关闭提示';
}
return '关闭提示';
},
// 关闭浏览器标签触发
logout() {
// 运行环境
let baseURL = process.env.VUE_APP_URL;
if (process.env.NODE_ENV === "production") {
baseURL = window.Glob.BaseUrl + process.env.VUE_APP_API;
}
fetch(baseURL + '/login/loginOut?userId=admin', {
method: 'GET',
mode: 'no-cors',
headers: {'Content-Type': 'application/json'},
keepalive: true
});
},
}
问题:刷新和关闭浏览器标签时都会触发,暂时无法限制刷新页面不触发该事件,有想法的小伙伴请留言呢。