使用store.js监听localStorage跨标签页变更失效问题求助
跨标签页监听localStorage变更的问题解决
我来帮你搞定这个跨标签页没法监听client值变更的问题!
问题根源
你用的store.js的observe方法,本质是拦截了自身的set方法来触发回调——也就是说,只有在当前标签页调用store.set修改值时,才会触发它的监听逻辑。但当其他标签页修改localStorage时,浏览器会触发原生的storage事件,而store.js默认没有把这个事件和它的observe回调绑定起来,所以其他标签页完全没反应。
解决方案
下面给你两种可行的方案,选你顺手的来用:
方案1:扩展store.js,让它支持跨标签页监听
我们可以给store.js的observe方法加一层包装,同时监听浏览器原生的storage事件,这样不管是同标签页还是跨标签页的变更都能捕获到:
// 放在引入store.js之后执行这段代码 (function() { // 先保存原来的observe方法,避免覆盖 if (!store._originalObserve) { store._originalObserve = store.observe; store.observe = function(key, callback) { // 保留原有的同标签页监听逻辑 store._originalObserve(key, callback); // 新增跨标签页的监听:监听原生storage事件 window.addEventListener('storage', function(e) { // 只处理我们关心的key,且值确实发生了变化 if (e.key === key && e.newValue !== e.oldValue) { // 解析旧值(store.js会自动序列化对象,所以要转成JSON) const oldVal = e.oldValue ? JSON.parse(e.oldValue) : undefined; // 用store.get获取新值(自动反序列化) const newVal = store.get(key); // 触发原来的回调 callback(newVal, oldVal); } }); }; } })(); // 你原来的代码不用改,直接用就行 store.set('client', { 'name': Math.random() }); $('#mybtn1').click(function() { store.set('client', { 'name': Math.random() }); }); store.observe('client', function(val, oldVal) { console.log('changed'); console.log('new value:', val); console.log('old value:', oldVal); });
方案2:用原生storage事件结合jQuery实现
如果你不想修改store.js的逻辑,也可以直接用浏览器原生的storage事件,再单独处理同标签页的变更:
// 原有的保存逻辑不变 store.set('client', { 'name': Math.random() }); $('#mybtn1').click(function() { store.set('client', { 'name': Math.random() }); }); // 处理跨标签页的变更:监听storage事件 $(window).on('storage', function(e) { const nativeEvent = e.originalEvent; // 获取原生事件对象 if (nativeEvent.key === 'client') { console.log('changed (cross-tab)'); const newVal = store.get('client'); const oldVal = nativeEvent.oldValue ? JSON.parse(nativeEvent.oldValue) : undefined; console.log('new value:', newVal); console.log('old value:', oldVal); } }); // 处理同标签页的变更:给store.set加钩子 const originalSet = store.set; store.set = function(key, value) { const oldVal = store.get(key); // 执行原来的set逻辑 originalSet.call(store, key, value); // 如果是我们关心的key,手动触发回调 if (key === 'client') { console.log('changed (same-tab)'); console.log('new value:', value); console.log('old value:', oldVal); } };
注意事项
- 原生
storage事件只会在其他标签页修改localStorage时触发,当前标签页修改不会触发,所以必须单独处理同标签页的情况。 store.js存储对象时会自动用JSON.stringify序列化,所以读取旧值时要记得用JSON.parse解析成对象,不然拿到的是字符串。
内容的提问来源于stack exchange,提问作者Adarsh Madrecha
相关产品推荐
相关产品推荐

