版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
背景:一个账号下有多个商户,且登录状态后端保存,当前账号信息存在localstorage中
第一个想法:一个事件storge当localstorage里的值发生变化时触发,(可以不在当前页面触发)
window.addEventListener('storage', (e) => {
// console.log('google');
// 事件对象 其中e.key是发生变化的localStorage里的key e.oldValue变化之前的值,e.newValue变化之后的值
// console.log(e);
this.merchantName = JSON.parse(localStorage.getItem('userinfo')).merchantName;
console.log(this.merchantName);
localStorage.setItem('null_item', null);
if ((e.key === 'userinfo')) {
console.log(e);
if (!e.newValue) return;
const oldValue = JSON.parse(e.oldValue);
const newValue = JSON.parse( );
if (oldValue.merchantName !== newValue.merchantName) {
this.dialogVisible = true;
this.merchantName = newValue.merchantName;
}
}
});
在谷歌浏览器是没有问题的,然而奇葩的IE(10,11)都不行,它监听不到localstorage里值得变化,感觉IE中,localstorage是不共享的,和sessionstorage差不多。所以这个事件pass
第二个,找到了visibilitychange事件,窗口下切换tab页时触发,document.visibilityState值有两个,visible和hidden
新值和旧值,旧值我取的是sessionstorage里的值,之前会把当前账户在session和local里都存一份。
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
const oldValue = JSON.parse(sessionStorage.getItem('userinfo')).merchantName;
const newValue = JSON.parse(localStorage.getItem('userinfo')).merchantName;;
if (oldValue !== newValue) {
this.dialogVisible = true;
}
}
});
不知道有没有发现,对的,IE又有了兼容问题,因为我的newValue又取了localstorage里的值,他不是最新值,所以没有变化,好悲伤。想了好久,忽然想到,当前状态后端也存了一份,所以代码:
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
api.get('/rest/current').then((data) => {
const oldValue = JSON.parse(sessionStorage.getItem('userinfo')).merchantName;
this.merchantName = data.data.merchantName;
if (oldValue !== this.merchantName) {
this.dialogVisible = true;
}
});
}
});
有没有很完美,然而这不完美,我又发现个一个很恐怖的bug,visibilitychange里代码会执行很多很多遍,因为有请求,所以更恐怖,一个接口会发送好多遍,我找了很久很久,想到了节流阀,然而真的没有用,连规律都没有找到,马上就要绝望的时候,问了我们老大,老大不愧是老大,人家找了一会就发现了问题(冒泡or捕获)addEventListener,对的,就是在最后加一个false。
- true - 事件句柄在捕获阶段执行
- false- false- 默认。事件句柄在冒泡阶段执行
完整代码:
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
api.get('/rest/current').then((data) => {
const oldValue = JSON.parse(sessionStorage.getItem('userinfo')).merchantName;
this.merchantName = data.data.merchantName;
if (oldValue !== this.merchantName) {
this.dialogVisible = true;
}
});
}
}, false);
这样就解决了,哦,对了,还有一个问题,如果不是在一个窗口下,visibilitychange是不会触发的