基于localStorage和UserData的demo
这两天系统学习了 localStorage和UserData,本文前半部分是一些网络上关于这方面的流行 的博文,用于备忘。 后半部分是两个自己做过的demo和封装好的兼容ie的api。
本地存储解决方案很多,比如Flash SharedObject、Google Gears、Cookie、DOM Storage、User Data、window.name、Silverlight、Open Database等。
Cookie: 在web中得到广泛应用,但局限性非常明显,容量太小,有些站点会因为出于安全的考虑而禁用cookie,cookie没有想象中的那么安全,Cookie 的内容会随着页面请求一并发往服务器。
Flash SharedObject: 使用的是kissy的store模块来调用Flash SharedObject。Flash SharedObject的优点是容量适中,基本上不存在兼容性问题,缺点是要在页面中引入特定的swf和js文件,增加额外负担,处理繁琐;还是有部分机子没有flash运行环境。
Google Gears: Google的离线方案,已经停止更新,官方推荐使用html5的localStorage方案。
User Data: 是微软为IE专门在系统中开辟的一块存储空间,所以说只支持Windows+IE的组合,实际测试在2000(IE5.5)、XP(IE6、IE7),Vista(IE7)下都是可以正常使用的。在XP下,一般位于C:\Documents and Settings\用户名\UserData,有些时候会在C:\Documents and Settings\用户名\Application Data\Microsoft\Internet Explorer\UserData。在Vista下,位于C:\Users\用户名\AppData\Roaming\Microsoft\Internet Explorer\UserData;单个文件的大小限制是128KB,一个域名下总共可以保存1024KB的文件,文件个数应该没有限制。在受限站点里这两个值分别是64KB和640KB,所以如果考虑到各种情况的话,单个文件最好能控制64KB以下。
localStorage: 相对于上述本地存储方案,localStorage有自身的优点:容量大、易用、强大、原生支持;缺点是兼容性差些(chrome, safari, firefox,IE 9,IE8都支持 localStorage,主要是IE8以下版本不支持)、安全性也差些(所以请勿使用localStorage保存敏感信息)。
主要说说localStorage和UserData:
UserData
- 基本语法 :
XML: <Prefix: CustomTag id=sID style=”behavior:url(‘#default#userData’)” />
HTML: <ELEMENT style=”behavior:url(‘#default#userData’)” id=sID> - Script:
object.style.behavior = “url(‘#default#userData’)”
object.addBehavior (“#default#userData”) - 属性:
expires 设置或者获取 userData behavior 保存数据的失效日期。
XMLDocument 获取 XML 的引用。 - 方法:
getAttribute() 获取指定的属性值。
load(object) 从 userData 存储区载入存储的对象数据。
removeAttribute() 移除对象的指定属性。
save(object) 将对象数据存储到一个 userData 存储区。
setAttribute() 设置指定的属性值。
localStorage
原生的接口:
- localStorage.getItem(key):获取指定key本地存储的值
- localStorage.setItem(key,value):将value存储到key字段
- localStorage.removeItem(key):删除指定key本地存储的值
- localStorage.clear() :清除所有键值
- localStorage.length:键值长度
- localStorage.key(i) :索引第i个键值
具体用法如下,已经封装好:
1 (function(){
2 baiduUserData = {
3 _data : null,
4 _defExpires : null,
5 _saveFile : null,
6 setDefExpires : function(expires){
7 var This = this;
8 This._defExpires = expires || 365;
9 },
10 setSaveFile : function(s){
11 var This = this;
12 This._saveFile = s || window.location.hostname;
13 },
14 _init : function(){
15 var This = this;
16 if (!This._data){
17 try {
18 This._data = document.createElement('input');
19 This._data.type = "hidden";
20 This._data.addBehavior("#default#userData"); //这里一定是#default#userData
21 document.body.appendChild(This._data);
22 } catch(e){
23 return false;
24 }
25 }
26 return true;
27 },
28
29 setItem : function(opt){ //opt={file: ,key: ,value: ,e: }
30 var This = this;
31 if(This._init()){
32 This.setDefExpires(opt.e);
33 var expires = new Date();
34 expires.setDate(expires.getDate()+This._defExpires);
35 This._data.expires = expires.toUTCString();
36
37 opt.value = typeof(opt.value) == "string" ? opt.value : T.json.stringify(opt.value);
38 This.setSaveFile(opt.file);
39 This._data.load(This._saveFile);
40 This._data.setAttribute(opt.key,opt.value);
41 This._data.save(This._saveFile);
42 }
43 },
44
45 getItem : function(opt){ //opt={file: ,key: }
46 var This = this;
47 if(This._init()){
48 This.setSaveFile(opt.file);
49 This._data.load(This._saveFile);
50 return This._data.getAttribute(opt.key);
51 }
52 },
53
54 removeItem : function(opt){ //opt={file: ,key: }
55 var This = this;
56 if(This._init()){
57 This.setSaveFile(opt.file);
58 This._data.load(This._saveFile);
59 This._data.removeAttribute(opt.key);
60 This._data.save(This._saveFile);
61 }
62 }
63 };
64
65
66
67 /*对外接口*/
68
69 baiduStorage = {
70 /**
71 * 调用baiduStorage.getItem({file: , key: });其中file可选,用于Userdata指定读取的文件名。key必选
72 */
73 getItem : function(opt){
74 if(window.localStorage){
75 return localStorage.getItem(opt.key);
76 }
77 else return baiduUserData.getItem(opt);
78 },
79 /**
80 * 调用baiduStorage.setItem({file: , key: ,value:, e:}); key,value必选,file可选,用于Userdata指定读取的文件名.e可选,用于UserData指定到期时间
81 */
82 setItem : function(opt){
83 if(window.localStorage){
84 opt.value = typeof(opt.value) == "string" ? opt.value : T.json.stringify(opt.value);
85 localStorage.setItem(opt.key,opt.value);
86 }
87 else baiduUserData.setItem(opt);
88 },
89 /**
90 * 调用baiduStorage.removeItem({file: , key: ,clear:});其中file可选,用于Userdata指定读取的文件名.clear可选(boolean),true表示清空,false或空时就只remove掉key.
91 */
92 removeItem : function(opt){
93 if(window.localStorage){
94 if(opt.clear) localStorage.clear();
95 else localStorage.removeItem(opt.key);
96 }
97 else baiduUserData.removeItem(opt);
98 }
99 };
100 })();
事件绑定:
onStorage事件对象属性测试 以下是本人机子的测试结果
|
key |
oldValue |
newValue |
url |
storageArea(json 格式,改变后所有的key:val) |
IE8 |
无 |
无 |
无 |
有 |
无 |
Firefox6 |
有 |
有 |
有 |
有 |
有 |
Chrome15 |
有 |
有 |
有 |
有 |
有 |
Safari5.1 |
有 |
有 |
有 |
有 |
有 |
Opera10 |
有 |
有 |
有 |
有 |
有(多一个length,值为key的数量) |
此外,不同的浏览器事件注册的方式以及对象也不一致。
onStorage事件注册对象,以下是本人机子的测试结果
|
事件注册对象 |
备注 |
IE8 |
document |
不能是window绑定 |
Firefox6 |
Window |
|
Chrome5 |
Window |
|
Safari5.1 |
Window |
|
Opera11.5 |
window |
|
注:IE8既支持UserData又支持localStorage
:IE6,7不支持onstorage事件,需要用时间轮询来捕获键值的变化。
1 (function(){
2 function myEvt(e){
3 if(!e) e=window.event;
4 alert("key---"+e.key);
5 alert("newValue---"+e.newValue);
6 alert("oldValue---"+e.oldValue);
7 alert("url---"+e.url);
8 alert("storageArea---"+T.json.stringify(e.storageArea));
9 }
10 if(window.addEventListener){
11 window.addEventListener("storage",function(e){myEvt(e);},false);
12 }
13 else{
14 document.attachEvent("onstorage",function(e){myEvt(e);});
15 }
16
17 if(document.all){
18 var old = baiduStorage.getItem({key:"a"});
19 function checkUpdate(){
20 var newV = baiduStorage.getItem({key:"a"});
21 if(old != newV){
22 alert(newV);
23 old = newV;
24 }
25 }
26 setInterval(function(){checkUpdate();},500);
27 }
28 })();
Demo
1,验证onstorage事件.打开两个tab。(除IE6,7外,都能alert出onstorage事件的属性。IE6,7的只能alert出变化后的值).
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
5 <title>本地存储</title>
6 <script type="text/javascript" src="tangram_stringify.js"></script>
7 <script type="text/javascript" src="storage_api.js"></script>
8 </head>
9
10 <body>
11 <div id="ans1"></div>
12 <script type="text/javascript">
13 baiduStorage.setItem({key:"a",value:20});
14 function changeData(){
15 var t1 = baiduStorage.getItem({key:"a"});
16 ++t1;
17 alert(t1);
18 baiduStorage.setItem({key:"a",value:t1});
19 }
20
21 </script>
22 <input type="button" id="ce" onclick="changeData();" value="改变键值"/>
23 </body>
24 </html>
(点击此页面中的按钮,第二个页面会alert出事件的各个属性)。
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
5 <title>本地存储</title>
6 <script type="text/javascript" src="tangram_stringify.js"></script>
7 <script type="text/javascript" src="storage_api.js"></script>
8 <script type="text/javascript">
9 (function(){
10 function myEvt(e){
11 if(!e) e=window.event;
12 alert("key---"+e.key);
13 alert("newValue---"+e.newValue);
14 alert("oldValue---"+e.oldValue);
15 alert("url---"+e.url);
16 alert("storageArea---"+T.json.stringify(e.storageArea));
17 }
18 if(window.addEventListener){
19 window.addEventListener("storage",function(e){myEvt(e);},false);
20 }
21 else{
22 document.attachEvent("onstorage",function(e){myEvt(e);});
23 }
24
25 if(document.all){
26 var old = baiduStorage.getItem({key:"a"});
27 function checkUpdate(){
28 var newV = baiduStorage.getItem({key:"a"});
29 if(old != newV){
30 alert(newV);
31 old = newV;
32 }
33 }
34 setInterval(function(){checkUpdate();},500);
35 }
36 })();
37 </script>
38 </head>
39
40 <body>
41 </body>
42 </html>
2.基于localStorage和UserData模拟HI(同一浏览器下打开两个tab,在一个tab中输入信息后,第二个tab会跟进信息。兼容所有浏览器,包括IE6,7)
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
5 <title>基于localStorage和UserData模拟HI</title>
6 <script type="text/javascript" src="storage_api.js"></script>
7 <script type="text/javascript" src="tangram_stringify.js"></script>
8 <style type="text/css">
9 #wrap{margin:100px auto;height:500px;width:500px;border:1px solid #CCFFCC}
10 #top{height:350px; overflow:scroll;}
11 #sep{height:20px; background-color:#33CCFF}
12 #content{height:125px;width:500px;}
13 #s{float:right;}
14 h1{color:#3300FF; font-size:24px; font-family:"宋体";margin:50px auto 0 auto; text-align:center;}
15 #notice{display:none;}
16 </style>
17 </head>
18
19 <body>
20 <h1>基于localStorage和UserData模拟HI</h1>
21 <div id="wrap">
22 <div id="top"></div>
23 <div id="sep"></div>
24 <textarea id="content" rows="5" onclick="HI.hide_notice();"></textarea>
25 <input type="button" id="s" value="发送" onclick="HI.send();" />
26 <p id="notice">发送内容不能为空</p>
27 </div>
28 <script type="text/javascript">
29 var HI = {
30 _content : null,
31 init : function(){
32 var This = this;
33
34 baiduStorage.setItem({key:"content",value:''});
35 This._content = '';
36
37 if(window.addEventListener){
38 window.addEventListener("storage",function(e){
39 if(!e) e=window.event;
40 This._content = baiduStorage.getItem({key:"content"});
41 document.getElementById("top").innerHTML = This._content;
42 },false);
43 }
44
45 if(document.all){
46 function checkUpdate(){
47 var newV = baiduStorage.getItem({key:"content"});
48 if(This._content != newV){
49 document.getElementById("top").innerHTML = newV;
50 This._content = newV;
51 }
52 }
53 setInterval(function(){checkUpdate();},500);
54 }
55 },
56 send : function(){
57 var temp = document.getElementById("content").value.replace(/(^\s*)(\s*$)/g,'');
58 if(temp == ''){
59 document.getElementById("notice").style.display = "block";
60 document.getElementById("content").value = "";
61 return false;
62 }
63 var This = this;
64 This._content = baiduStorage.getItem({key:"content"});
65
66 This._content += document.getElementById("content").value + '<br/>';
67 baiduStorage.setItem({key:"content",value:This._content});
68 document.getElementById("top").innerHTML = This._content;
69 document.getElementById("content").value = '';
70 },
71 hide_notice: function(){
72 document.getElementById("notice").style.display = "none";
73 }
74 }
75 HI.init();
76
77 </script>
78 </body>
79 </html>
需要跟进的地方:
1. 按照网上所说的UserData路径,在IE下的UserData文件仍然找不到。
2. 自己封装的baiduStorage的api考虑到的需求可能不周,若有新需求可以跟进。