存储事件未触发

42

附加事件:

$(window).on("storage", function (e) {
   //callback not getting hit
});
尝试触发事件:
localStorage.setItem("test", "123");

我打开了两个标签页,都在监听存储事件。我可以看到localStorage在两个标签页上都正确更新。但是当我在一个标签页上更改localStorage时,另一个标签页从未触发该事件。有任何想法吗?

已在Chrome / Firefox上尝试。 域格式为https://www.xxx.yyy.zzz

8个回答

61

正如其他答案中所指出的那样,storage 事件只有在其他浏览器选项卡/窗口(相同应用程序的)更改了 localStorage,而不是在当前选项卡的上下文中时,才会被监听器所捕获。

检测 当前选项卡 中的存储更改:

window.addEventListener('storage', console.log)

window.localStorage.setItem('test', '123')
window.dispatchEvent( new Event('storage') ) // <----- 

手动触发了storage事件。

这将在其他标签页/窗口(同一应用程序)上有效地触发storage事件监听器两次,但在某些情况下,这不应该是一个问题。


1
真是太棒了 :) - Nikhil sHETH

54

当在同一域名下的不同页面修改 Storage 对象时,会触发 StorageEvent 事件。

引自 MDN

无论何时修改 Storage 对象,都会触发 StorageEvent 事件。

这在进行更改的同一页面上无法工作 - 实际上,它是用于对使用存储的域中的其他页面同步所做更改的一种方式。


9

除了上面vsync的回答之外,您还可以触发StorageEvent而不是Event并传递一个对象,以便触发的事件与浏览器默认值匹配。

const oldValue = window.localStorage.getItem('test');
window.localStorage.setItem('test', newValue);
const event = new StorageEvent('storage', {
  key: 'test',
  oldValue,
  newValue,
  ...
});

window.dispatchEvent(event);

4
如果在不同的标签页之间进行测试,仍然看不到事件触发... 我发现只有在键已经存在时事件才会触发。 这似乎更像是一个"onchange"事件。 为"localStorage"键设置一个默认值,即使是"undefined",然后测试。 我认为这是Chrome的一个bug,因为Firefox和Safari会正确地触发,但事实就是这样。

2022年,我已经点赞并确认了这一点。 - Mohab Khaled

1

1
“在我删除了有问题的那行代码后,事件就正常工作了。” 你删除了哪一行有问题的代码呢? - gurvinder372
我重新表达了答案,现在更清楚了吗?我在一个主机为abc.xyz.com的页面上设置了document.domain = xyz.com - MichaelAttard

0

你可以随时使用像localDataStorage这样的实用工具来代替你触发事件,在同一个窗口/标签页中,每当键值发生更改时,例如通过set或remove方法进行的更改。你还可以使用它来透明地设置/获取以下任何一种“类型”:数组、布尔值、日期、浮点数、整数、空值、对象或字符串。

[免责声明]我是该实用程序的作者[/免责声明]

一旦你实例化了该实用程序,以下代码片段将允许你监视事件:

function localStorageChangeEvents( e ) {
    console.log(
        "timestamp: "     + e.detail.timestamp + " (" + new Date( e.detail.timestamp ) + ")" + "\n" +
        "key: "           + e.detail.key     + "\n" +
        "old value: "     + e.detail.oldval  + "\n" +
        "new value: "     + e.detail.newval  + "\n"
    );
};
document.addEventListener(
    "localDataStorage"
    , localStorageChangeEvents
    , false
);

那太难读了。你能在那个仓库里也发布一下原始源代码吗?我其实很好奇你的逻辑是什么。 - yuyu5
明白了,你说得对。我已经更新了存储库中的源文件。 - Mac
2
这个问题被踩的原因除了难以阅读(已经得到修复)之外,还有其他的吗? - JamesWilson

0
我试图在一个标签页注销后,从其他标签页注销。我遇到的问题是一遍又一遍地设置相同的值。
这就是为什么存储事件在其他标签页中没有触发的原因。一个简单的解决方法是每次添加一个盐/随机内容来触发事件。

 window.localStorage.setItem('logout-event',Math.random().toString())

然后这些事件就可以在其他选项卡中使用了!处理来自其他选项卡的事件的更好方法是使用BroadcastChannel


0
window.addEventListener('storage', function (e) {
      console.log("storage event occured here");
},false);

存储监听器在源选项卡之外的其他选项卡中被调用。只需将调试器添加到其他选项卡即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接