如何使用 jQuery 为所有浏览器绑定到 localStorage 更改事件?

Posted

技术标签:

【中文标题】如何使用 jQuery 为所有浏览器绑定到 localStorage 更改事件?【英文标题】:How to bind to localStorage change event using jQuery for all browsers? 【发布时间】:2011-06-07 23:54:13 【问题描述】:

如何使用 jQuery 将函数绑定到 html5 localStorage 更改事件?

$(function () 

  $(window).bind('storage', function (e) 
    alert('storage changed');
  );

  localStorage.setItem('a', 'test');

);

我已尝试上述方法,但未显示警报。

更新:它在 Firefox 3.6 中有效,但在 Chrome 8 或 IE 8 中无效,所以问题应该是“”

【问题讨论】:

对我来说很好。你也许应该添加一点特征检测.. if(!localStorage in window) alert('foobar'); typeofnan.blogspot.com/2010/09/… @jAndy 你在使用 safari,我也测试了他的解决方案,但结果相同,我认为它可能不受支持 这适用于 Firefox,但不适用于 Chrome。确实,我也无法让 Chrome 与 addEventListener 一起使用。 是的,你可能需要创建一个包装器 很奇怪。 Chrome 不能用了?我知道过去是这样的。 【参考方案1】:

事实证明这实际上工作正常,我误解了the specification

当 setItem()、removeItem() 和 clear() 方法在与本地存储区域关联的 Storage 对象 x 上调用时,如果这些方法做了某些事情,则在每个 Document 对象中,其 Window 对象的 localStorage 属性的存储对象与同一个存储区域相关联,除了x,必须触发存储事件

换句话说,每个窗口/选项卡除了都会触发一个存储事件,该事件更新了localStorage 对象并引发了该事件。

所以事件没有被触发,因为我只打开了一个窗口/选项卡。如果我将上面的代码放在一个页面中并在两个选项卡中打开该页面,我会在第二个选项卡中看到该事件。

This answer on the problem 包含更多详细信息。

【讨论】:

Firefox 的规范实现(在 3.6 中)是不正确的,因为它会在更新 localStorage 的窗口中触发事件 Firefox 似乎已经纠正了这个问题,但是 IE9 和 IE10 仍然没有遵循规范。他们在所有窗口/选项卡中触发事件,包括发起更改的那个。我在这里向微软提出了这个错误(不幸的是需要登录):connect.microsoft.com/IE/feedback/details/774798/… 谢谢!两天来我一直在发疯,想知道为什么当我什么都不做的时候我的本地存储在我眼前更新了两次……我打开了另一个窗口,另一个用户登录了,它存储了不同的数据。但是,当然,在域之间共享本地存储,这就是原因!再次感谢【参考方案2】:

以下是在 JQuery 中的操作方法:

 $(window).bind('storage', function (e) 
     console.log(e.originalEvent.key, e.originalEvent.newValue);
 );

直接访问e.key 不起作用。您需要使用e.originalEvent.key

有些浏览器只会将存储通知发送到其他选项卡,而有些则不会。 (Firefox 会将存储事件发送到它自己的选项卡,但 key 设置为 null,看起来是这样)。

【讨论】:

Firefox 修复了这个错误,它的工作方式与 Chrome 相同,但 IE 11 仍然存在错误,因此它会在自己的选项卡中触发一个事件...【参考方案3】:

值得一提的是,只有在项目实际上发生变化时,才会在.setItem 上调用事件处理程序。我一直在努力让它工作,直到我意识到你不能继续使用相同的值运行 setItem。

我使用的是 Chrome 版本 54.0.2840.71 m

这是一个测试(在两个浏览器选项卡中打开)。

if (window.addEventListener)
            addEventListener('storage', storage_event, false);
        else if (window.attachEvent)
            attachEvent('onstorage', storage_event, false);
        function storage_event(e) 
            console.log("Time is now "+ e.newValue);
        

        setInterval(function () 
            var time=new Date().getTime();
            localStorage.setItem("time", time);
            console.log("Setting time to "+time);
        , 1000)

【讨论】:

所有浏览器都支持addEventListener (caniuse.com/#search=addEventListener)【参考方案4】:

只要键值发生更改,例如由 set 或 remove 方法进行的更改,您始终可以使用localDataStorage 之类的实用程序在同一窗口/选项卡中为您触发事件。您还可以使用它来透明地设置/获取以下任何“类型”:Array、Boolean、Date、Float、Integer、Null、Object 或 String。

[DISCLAIMER] 我是该实用程序的作者 [/DISCLAIMER]

一旦您实例化该实用程序,以下 sn-p 将允许您监视事件(在 vanilla JS 中,因为已经给出了 jQuery 示例):

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
);

【讨论】:

以上是关于如何使用 jQuery 为所有浏览器绑定到 localStorage 更改事件?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery事件详解之$(document).ready()

如何从 jQuery 中的“滚动”事件中取消绑定所有先前添加的事件? [复制]

如何将df.loc []应用于多行并应用转换?

jQuery事件

jquery如何 绑定Load事件 到一个元素上

jQuery 之 事件方法