localStorage、sessionStorage详解,以及storage事件使用

有关localStorage和sessionStorage的特性。

localStorage本身带有方法有

  添加键值对:localStorage.setItem(key,value),如果key存在时,更新value。

  获取键值:localStorage.getItem(key),如果key不存在返回null。

  删除键值对:localStorage.removeItem(key)。key对应的数据将会全部删除。

  清除所有键值对:localStorage.clear()。如果调用clear()方法,清空localStorage中所有信息,那么key、oldValue和newValue都会被设置为null。

  获取localStorage的属性名称(键名称):localStorage.key(index)。

     还有一个和普通对象不一样的属性length:

  获取localStorage中保存的键值对的数量:localStorage.length。

  下面这个例子用来获取localStorage的键值对

for(var i=0;i<localStorage.length;i++){
  console.log(localStorage.key(i)+ " : " + localStorage.getItem(localStorage.key(i)));
}

  

1、存储格式

localStorage对象的键和值只能是字符串,假设我们要保存一个对象到localStorage中,可以使用拼接的方式。当然也可以借助JSON类,将对象转换成字符串保存,然后在取出来的时候将json字符串转换成真正可用的json对象格式

存储JSON格式数据

JSON.stringify(data) 将一个对象转换成JSON格式的数据串,返回转换后的串
JSON.parse(data) 将数据解析成对象,返回解析后的对象

(虽然规范中可以存储其他原生类型的对象,但是目前为止没有浏览器对其进行实现)。

2、生命周期

在数据存储的时效性上,localStorage并不会像cookie那样可以设置数据存活的时限。也就是说,只要用户不主动删除,localStorage存储的数据将会永久存在。

sessionStorage生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,那么所有通过sessionStorage存储的数据也就被清空了。

3、存储位置

当然,对于localStorage数据的存储,是存在于本地的文件系统中的,例如,对于chrome来说,localStorage数据的存储位置是在:C:\Users\{userName}\AppData\Local\Google\Chrome\User Data\Default\Local Storage中。对于其他4大浏览器,大家可以自行查找进行查看。

4、数据共享

不同浏览器无法共享localStorage或sessionStorage中的信息。相同浏览器的不同页面间可以共享相同的localStorage(页面属于相同域名和端口),但是不同页面或标签页间无法共享sessionStorage的信息。这里需要注意的是,页面及标签页仅指顶级窗口,如果一个标签页包含多个iframe标签且他们属于同源页面,那么他们之间是可以共享sessionStorage的。

5、兼容性

可以看到,除IE外的其他浏览器很早的版本都支持了,对于IE低版本系列的浏览器,我们需要一个兼容方案来处理。

微软在IE5.0以后,自定义了一种持久化用户数据的概念userData,这种存储方式只有IE浏览器自己支持。来看看其如何操作——

(function(win) {
    // 对于IE,且不支持localStorage的浏览器
    // 即针对IE6/7
    if ( typeof win.attachEvent != "undefined" && typeof win.localStorage == "undefined") {
        var localFileName = "_simulateLocalStorage", 
            expires = 365,
            formField = null;
        
        // 设置有效期为365天
        var expire = new Date();
        expire.setDate(expires + expire.getDate());
        
        formField = document.createElement("input");
        formField.type = "hidden";
        formField.addBehavior('#default#userData');
        
        document.body.appendChild(formField);
    
        var storage = {
            setItem : function(key, value) {
                formField.load(localFileName);
                formField.setAttribute(key, value);
                formField.save(localFileName);
            },
            getItem : function(key) {
                formField.load(localFileName);
                return formField.getAttribute(key);
            },
            removeItem : function(key) {
                formField.load(localFileName);
                formField.removeAttribute(key);
                formField.save(localFileName);
            },
            clear : function() {
                formField.load(localFileName);
                var d = new Date();
                d.setDate(d.getDate() - 1);
                formField.expires = d.toUTCString();
                formField.save(localFileName);
            }
        };
    
        win["localStorage"] = storage;
    }
})(window);

  

这里仅仅是对IE兼容性的简单包装,下面的链接给出非常完善的针对localStorage兼容性的解决方案。

https://github.com/machao/localStorage

6、存储大小

对于HTML5的localStorage而言,其大小支持为5M(当然,各浏览器的大小差异还是有的)。对于IE的userData,用户数据的每个域最大为64KB。

7、应用场景

建议不要使用localStorage方式存储敏感信息,哪怕这些信息进行过加密。另外,对身份验证数据使用localStorage进行存储还不太成熟。我们知道,通常可以通过xss漏洞来获取到Cookie,然后用这个Cookie进行身份验证登录,但是浏览器可以通过HttpOnly来保护Cookie不被XSS攻击获取到。而localStorage存储没有对XSS攻击有任何防御机制,一旦出现XSS漏洞,那么存储在localStorage里的数据就极易被获取到。

 

storage事件:当存储的storage数据发生变化时都会触发它,但是它不同于click类的事件会冒泡和能取消,storage改变的时候,触发这个事件会调用所有同域下其他窗口的storage事件,不过它本身触发storage即当前窗口是不会触发这个事件的(当然ie这个特例除外,它包含自己本事也会触发storage事件)。

在使用 Storage 进行存取操作的同时,如果需要对存取操作进行监听,可以使用 HTML5 Web Storage api 内置的事件监听器对数据进行监控。只要 Storage 存储的数据有任何变动,Storage 监听器都能捕获。

interface Storage : Event{
    readonly attribute DOMString key;
    readonly attribute DOMString? oldValue;
    readonly attribute DOMString? newValue;
    readonly attribute DOMString url;
    readonly attribute Storage? storageArea;
    void initStorageEvent(in DOMString typeArg,
      in boolean canBubbleArg,
      in boolean cancelableArg,
      in DOMString keyArg,
      in DOMString oldValueArg,
      in DOMString newValueArg,
      in DOMString urlArg,
      in Storage storageAreaArg);
};

  

不难看出其中包含以下属性:

  1. key 属性表示存储中的键名
  2. oldValue 属性表示数据更新前的键值,newValue 属性表示数据更新后的键值。如果数据为新添加的,则 oldValue 属性值为 null。如果数据通过 removeItem 被删除,则 newValue 属性值为 null 。如果 Storage 调用的是 clear 方法,则事件中的 key 、oldValue 、newValue 都是为 null
  3. url 属性记录 Storage 时间发生时的源地址
  4. StorageArea 属性指向事件监听对应的 Storage 对象

Storage 事件可以使用 W3C 标准的注册事件方法 addEventListenter 进行注册监听。例如:

window.addEventlistener("storage",showStorageEvent,false);

function showStorageEvent(e){

    console.log(e)

}

  

举例:

页面a下,有个input框用来存储store,它自身绑定了storage事件,这个时候写入新的数据点击保存,这时新的sotre数据保存了,但是页面a的storage事件没触发,

而页面b下,绑定的storage事件则触发了。(ps:前提页面a和b在同域下,并都是打开状态不同窗口);

页面a代码:

 1 <!DOCTYPE html> 
 2 <html> 
 3 <head> 
 4   <meta charset="utf-8"> 
 5   <title></title> 
 6 </head> 
 7 <body> 
 8 <input type="text" placeholder="input date to save"> 
 9 <button>save</button> 
10 <script> 
11   (function(D){ 
12     var val = D.getElementsByTagName("input")[0], 
13       btn = D.getElementsByTagName("button")[0]; 
14     btn.onclick = function(){ 
15       var value = val.value; 
16       if(!value) return; 
17       localStorage.setItem("key", val.value); 
18     }; 
19     window.addEventListener("storage", function(e){ 
20       console.log(e); 
21     }); 
22   })(document); 
23 </script> 
24 </body> 
25 </html> 

 

页面b代码:

 1 <!DOCTYPE html> 
 2 <html> 
 3 <head> 
 4   <meta charset="utf-8"> 
 5   <title></title> 
 6 </head> 
 7 <body> 
 8 <script> 
 9   window.addEventListener("storage", function(e){ 
10     console.log(e); 
11     document.write("oldValue: "+ e.oldValue + " newValue:" + e.newValue) 
12   }); 
13    
14 </script> 
15 </body> 
16 </html> 

 

看到这里是不是很疑惑那storage事件到底有什么用,多窗口间多通信用到它就是最好选择了,比如某块公用内容区域基础数据部分都是从store中提取的,这个区域中大多数页面中都有,当用户打开多个页面时,在其中一个页面做了数据修改,那其他页面同步更新是不是很方便(当前页面就要用其他方式处理了),当然用于窗口间通信它作用不仅仅如此,更多的大家可以利用它特性去发挥。

在上面的demo页面b中storage的events对象的属性常用的如下: 

 oldValue:更新前的值。如果该键为新增加,则这个属性为null。 

 newValue:更新后的值。如果该键被删除,则这个属性为null。

 url:原始触发storage事件的那个网页的网址。 

 key:存储store的key名;

posted @ 2017-02-24 16:44  WXUECHAO  阅读(479)  评论(0编辑  收藏  举报