如何实时监测storage的变化
一、不同浏览器页签间的监听(sessionStorage、localstorage、vuex的变化都可以监听到)
使用场景:同一个浏览器,以用户最后一次登录账号为准(使用localStorage存储)。
mounted() {
window.addEventListener('storage', (e) => {
console.log("storage值发生变化后触发:", e)
});
},
弊端:同一个浏览器页签,修改storage的值,监听不到
二、同浏览器页签的监听(sessionStorage、localstorage均可)
使用场景:storage发生变化,执行某些方法。
main.js中:(sessionStarage雷同)
let orignalSetItem = window.localStorage.setItem; // 原生localStorage.setItem方法
localStorage.setItem = function(key,newValue){
let setItemEvent = new Event("setItemEvent"); // 重写注册setItem
setItemEvent.key = key;
setItemEvent.newValue = newValue;
window.dispatchEvent(setItemEvent); // 派发setItem
orignalSetItem.apply(this, arguments); // 设置值
}
上面的方法在火狐浏览器上遇到了问题,即监听失效了!原因是因为火狐浏览器把我们重写的setItem方法当作字符串存下来了(见图1-1)详细解释看这里~
因此我们使用
Object.defineProperty
去改写Storage的方法。
// 用闭包实现局部对象storage(注意Storage的方法都重写一遍,不然调用其对象原型方法会报错。)
var localStorageMock = (function(win) {
var storage = win.localStorage;
return {
setItem: function(key, value) {
var setItemEvent = new Event("setItemEvent");
var oldValue = storage[key];
setItemEvent.key = key;
// 新旧值深度判断,派发监听事件
if (oldValue !== value) {
setItemEvent.newValue = value;
setItemEvent.oldValue = oldValue;
win.dispatchEvent(setItemEvent);
storage[key] = value;
return true;
}
return false;
},
getItem: function(key) {
return storage[key];
},
removeItem: function(key) {
storage[key] = null;
return true;
},
clear: function() {
storage.clear();
return true;
},
key: function (index) {
return storage.key(index);
}
};
}(window));
Object.defineProperty(window, 'localStorage', { value: localStorageMock, writable: true });
使用:
window.addEventListener("setItemEvent", (e) => {
console.log("localStorage值发生变化后触发:", e.newValue);
});
弊端:不同浏览器页签(相同地址),修改storage的值,监听不到
三、浏览器页签的监听(sessionStorage、localstorage均可)
mounted() {
window.addEventListener('storage', (e) => {
console.log("别的浏览器页签storage发生变化啦:", e)
});
window.addEventListener("setItemEvent", (e) => {
console.log("localStorage值发生变化后触发:", e.newValue);
});
},
这样,不管是同浏览器页签还是不同浏览器页签,就都能监听到啦~