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); };
不难看出其中包含以下属性:
- key 属性表示存储中的键名
- oldValue 属性表示数据更新前的键值,newValue 属性表示数据更新后的键值。如果数据为新添加的,则 oldValue 属性值为 null。如果数据通过 removeItem 被删除,则 newValue 属性值为 null 。如果 Storage 调用的是 clear 方法,则事件中的 key 、oldValue 、newValue 都是为 null
- url 属性记录 Storage 时间发生时的源地址
- 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名;