13

Internet Explorer 10 在存储到本地存储的同一窗口上触发窗口“存储”事件。

似乎其他浏览器只在所有其他窗口上触发事件,所以我不必担心正在监听存储事件的窗口对其自身的存储做出反应。为什么 IE 会在错误的窗口中触发事件,如何在 IE 中复制标准行为?

4

2 回答 2

12

微软似乎意识到了这个问题,但看起来他们不会很快修复它:https ://connect.microsoft.com/IE/feedback/details/774798/localstorage-event-fired -在源窗口中

一种选择是您可以设计您的侦听器和设置器,以便它们在从已经与其状态一致的存储事件中获取信息时不会做出反应或存储。但是,这种设计模式可能比仅在其他窗口上触发存储事件更困难。

另一种选择是使本地存储在 IE 中的工作方式与在其他浏览器中的工作方式相同。我想出了一个公认的 hacky 但实用的解决方案,我在 IE10 中进行了测试,并希望在 IE8 和 IE9 中工作。我的 javascript 组件不直接收听窗口“存储”事件,而是收听我创建的“事件调度程序”。事件调度程序监听窗口“存储”事件并触发主干事件,除非存储事件源自该窗口。我检查此窗口是否存储此值的方法是使用自定义方法调用 setItem(),该方法为该值创建一个唯一 ID 并跟踪它,如下所示:

eventDispatcher.set = function(key, value) {
  var storageId = (new Date()).getTime();
  eventDispatcher.idList.push(storageId);
  localStorage.setItem(key, {value: value, id: storageId});
}

并且我的 eventDispatcher 监听存储事件并仅在其创建的 ID 列表不包含此值的 ID 时触发事件,如下所示:

$(window).on('storage', dispatchStorageEvent);
function dispatchStorageEvent(event) {
  var newValue = JSON.parse(event.originalEvent.newValue);
  if (eventDispatcher.idList.indexOf(newValue['id']) > -1) {
    return;
  }
  eventDispatcher.trigger("storageEvent:" + event.originalEvent.key, newValue['value']);
}

您可以添加更多代码来保持 idList 简短并首先将其创建为空数组,但为了清楚起见,我将其省略了。制作一个 eventDispatcher 来处理存储事件有点开销,但它可以使您的开发在浏览器之间保持一致。一个不那么 hacky 的解决方案是使用适当的锁定和排队机制,但这可能非常困难。

于 2013-08-16T03:57:21.833 回答
0

Explorer 在向存储提交新值时已经触发了一个事件。我发现它在我的 IE 11 中触发了 3 次 - 当旧值为 null 时,当新值为 null 时,然后将新值全部存储到存储中。我的解决方法是让监听器进入 setTimeout,我有一秒钟的时间,IE 不再第一次触发它(第一个窗口)。

于 2020-08-03T09:22:09.033 回答