本地存储替代cookie:qext.LocalStorage

转自:http://www.baidufe.com/item/af0bb5872f2a1ef337ce.html

文章写了都一年多了,一直没个合适的地方放,现在终于可以搬上来了。


背景

先看看各种本地存储的变革:

  • Cookies:浏览器均支持,容量为4KB

  • UserData:仅IE支持,容量为64KB

  • Flash:100KB

  • Google Gears SQLite :需要插件支持,容量无限制

  • LocalStorage:HTML5,容量为5M


现准备在项目中试图取代cookie的实现,基本分析如下:

  • 每次和服务器端进行交互,cookie都会在请求中被携带,cookie过多,也造成带宽的浪费

  • cookie的容量很小,或许无法满足当今互联网的本地存储需求

  • 在IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+等平台下,已经完全支持HTML5的LocalStorage

  • 在IE7即以下版本中,可以使用UserData来代替cookie,而且同样比cookie保险

  • 用户可能清cookie,但不见得知道去清UserData或者LocalStorage,这也增强了一道代码保险


到底用啥来取代?

  • UserData:仅IE可用

  • Flash:存储空间够了,也还挺好,可这玩意儿不是HTML原生的

  • Google Gears:存储空间没啥限制,就是得装额外的插件

  • HTML5-LocalStorage:官方建议每个站点可以本地存储5M的内容,非常大了

最后再分析一下现在咱们针对的浏览器:IE系列、FF、Chrome、Safari、Opera,外加双核的遨游、QQ浏览器、搜狗浏览器

其中,现在的FF、Chrome、Safari、Opera已经完全支持HTML5-LocalStorage

双核的那些个浏览器,要么Webkit内核,要么IE内核(大多都是IE8的内核了),所以这些也是支持HTML5-LocalStorage的

最后就剩IE7及其以下版本,对于专门的IE,就用它们自家提供的UserData了,处理很方便

总结:用UserData和HTML5-LocalStorage结合的方式,来取代cookie!


UserData的存储情况:


UserData行为通过将数据写入一个UserData存储区(UserData store)来保存数据,userData可以将数据以XML格式保存在客户端计算机上。

该数据将一直存在,除非你人为删除或者用脚本设置了该数据的失效期。

从上面的表格可以看出,就算是一个受限(Restricted)的站点,单个文档也能存64KB的数据,整个Domain也能装得下640KB的东西。


要了解更多UserData的东西,可以点击这里


关于Expires

我们都知道,采用cookie来进行本地数据缓存,可以设定一个生命周期,在IE中采用UserData进行替代,能完美的实现。

但是对于HTML5提供的LocalStorage则没有提供现成的API,来设置某本地存储的生命周期,只能采取一些极端的手段进行模拟实现。


关于数据的批量存储、提取、删除

一个好用的组件库,应该提供更加便捷的API,原生的cookie、UserData、LocalStorage都没有提供现成的接口可调用,所以,在这里,我们来包装一个,使其拥有这样的批量接口。


代码实现

1、IE中的UserData实现

原理很简单,就是创建一个HTML节点,为其增加一个行为(behavior):#default#userData,把待存储的数据放到该节点的属性上(setAttribute),再保存到本地即可(save)。


创建html实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
  * 创建并获取这个input:hidden实例
  * @return {HTMLInputElement} input:hidden实例
  * @private
  */
function  _getInstance(){
     //把UserData绑定到input:hidden上
     var  _input =  null ;
     //是的,不要惊讶,这里每次都会创建一个input:hidden并增加到DOM树种
     //目的是避免数据被重复写入,提早造成“磁盘空间写满”的Exception
     _input = document.createElement( "input" );
     _input.type =  "hidden" ;
     _input.addBehavior( "#default#userData" );
     document.body.appendChild(_input);
     return  _input;
}

本地数据存储:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
  * 将数据通过UserData的方式保存到本地,文件名为:文件名为:config.key[1].xml
  * @param {String} key 待存储数据的key,和config参数中的key是一样的
  * @param {Object} config 待存储数据相关配置
  * @cofnig {String} key 待存储数据的key
  * @config {String} value 待存储数据的内容
  * @config {String|Object} [expires] 数据的过期时间,可以是数字,单位是毫秒;也可以是日期对象,表示过期时间
  * @private
  */
function  __setItem(key,config){
     try  {
         var  input = _getInstance();
         //创建一个Storage对象
         var  storageInfo = config || {};
         //设置过期时间
         if (storageInfo.expires) {
             var  expires;
             //如果设置项里的expires为数字,则表示数据的能存活的毫秒数
             if  ( 'number'  ==  typeof  storageInfo.expires) {
                 expires =  new  Date();
                 expires.setTime(expires.getTime() + storageInfo.expires);
             }
             input.expires = expires.toUTCString();
         }
                 
         //存储数据
         input.setAttribute(storageInfo.key,storageInfo.value);
         //存储到本地文件,文件名为:storageInfo.key[1].xml
         input.save(storageInfo.key);
     catch  (e) {
     }
}


再看userData本地数据的读取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
  * 提取本地存储的数据
  * @param {String} config 待获取的存储数据相关配置
  * @cofnig {String} key 待获取的数据的key
  * @return {String} 本地存储的数据,获取不到时返回null
  * @example
  * qext.LocalStorage.get({
  *      key : "username"
  * });
  * @private
  */
function  _getItem(config){
     try  {
         var  input = _getInstance();
         //载入本地文件,文件名为:config.key[1].xml
         input.load(config.key);
         //取得数据
         return  input.getAttribute(config.key) ||  null ;
     catch  (e) {
         return  null ;           
     }
}


模拟remove操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
  * 移除某项存储数据
  * @param {Object} config 配置参数
  * @cofnig {String} key 待存储数据的key
  * @private
  */
function  _removeItem(config){
     try  {
         var  input = _getInstance();
         //载入存储区块
         input.load(config.key);
         //移除配置项
         input.removeAttribute(config.key);
         //强制使其过期
         var  expires =  new  Date();
         expires.setTime(expires.getTime() - 1);
         input.expires = expires.toUTCString();
         input.save(config.key);
               
         //从allkey中删除当前key          
         //下面的代码用来记录当前保存的key,便于以后clearAll
         var  result = _getItem({key : _clearAllKey});
         if (result) {
             result = result.replace( new  RegExp( "(^|\\|)"  + config.key +  "(\\||$)" , 'g' ), '' );
             result = {
                 key : _clearAllKey,
                 value : result
             };
             //保存键
             __setItem(_clearAllKey,result);
         }
               
     catch  (e) {
     }
}


2、再看HTML5-LocalStorage中expires的模拟:

在进行数据存储的时候,单独多存一个字段:key + ".expires",如果传入的expires为数字类型,单位则是毫秒(ms)

1
2
3
4
5
6
7
8
9
10
11
12
window.localStorage.setItem(storageInfo.key,storageInfo.value);
// 如果需要指定生命周期
if (config.expires) {
     var  expires;
     //如果设置项里的expires为数字,则表示数据的能存活的毫秒数
     if  ( 'number'  ==  typeof  storageInfo.expires) {
         expires =  new  Date();
         expires.setTime(expires.getTime() + storageInfo.expires);
     }
  
     window.localStorage.setItem(storageInfo.key +  ".expires" ,expires);
}


在数据读取的时候,通用读取这个字段,判断时间是否超出了生命周期

1
2
3
4
5
6
7
8
9
10
11
12
13
result = window.localStorage.getItem(config.key);
//过期时间判断,如果过期了,则移除该项
if (result) {
     var  expires = window.localStorage.getItem(config.key +  ".expires" );
     result = {
         value : result,
         expires : expires ?  new  Date(expires) :  null
     };
     if (result && result.expires && result.expires <  new  Date()) {
         result =  null ;
         window.localStorage.removeItem(config.key);
     }
}


3、提取所有key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
  * 获取所有的本地存储数据对应的key
  * <pre><code>
  * var keys = qext.LocalStorage.getAllKeys();
  * </code></pre>
  * @return {Array} 所有的key
  */
getAllKeys :  function (){
     var  result = [];
     //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+
     if (_isSupportLocalStorage) {
         var  key;
         for ( var  i = 0,len = window.localStorage.length;i < len;i++){
             key = window.localStorage.key(i);
             if (!/.+\.expires$/.test(key)) {
                 result.push(key);
             }
         }
     else  if (_isSupportUserData) {  //IE7及以下版本,采用UserData方式
         result = _getAllKeys();
     }
          
     return  result;
}


4、清除所有本地存储的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
  * 清除所有本地存储的数据
  * <pre><code>
  * qext.LocalStorage.clearAll();
  * </code></pre>
  */
clearAll :  function (){
     //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+
     if (_isSupportLocalStorage) {
         window.localStorage.clear();
     else  if (_isSupportUserData) {  //IE7及以下版本,采用UserData方式
         _clearAll();
     }
}


关于使用方法

1、数据存储:qext.LocalStorage.set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 保存单个对象到本地
qext.LocalStorage.set({
    key :  "username" ,
    value :  "baiduie" ,
    expires : 3600 * 1000   /*单位:ms*/
});
      
// 保存多个对象
qext.LocalStorage.set([{
    key :  "username" ,
    value :  "baiduie" ,
    expires : 3600 * 1000   /*单位:ms*/
},{
    key :  "password" ,
    value :  "zxlie" ,
    expires : 3600 * 1000   /*单位:ms*/
}]);


2、数据提取:qext.LocalStorage.get

1
2
3
4
5
6
7
8
9
10
11
12
13
//获取某一个本地存储,返回值为:{key:"",value:"",expires:""},未取到值时返回值为:null
  var  rst = qext.LocalStorage.get({
     key :  "username"
  });
     
  //获取多个本地存储,返回值为:["","",""],未取到值时返回值为:[null,null,null]
  qext.LocalStorage.get([{
     key :  "username"
  },{
     key :  "password"
  },{
     key :  "sex"
  }]);

3、数据删除:qext.LocalStorage.remove

1
2
3
4
5
6
7
8
9
10
11
12
13
//删除一个本地存储项
qext.LocalStorage.remove({
     key :  "username"
});
     
//删除多个本地存储项目
qext.LocalStorage.remove([{
     key :  "username"
},{
     key :  "password"
},{
     key :  "sex"
}]);

4、清空所有数据:qext.LocalStorage.clearAll

1
2
// 清空所有本地存储的数据
qext.LocalStorage.clearAll();

5、获取所有本地存储的key:qext.LocalStorage.getAllKes

1
2
// 获取所有本地存储的key
var  keys = qext.LocalStorage.getAllKeys();


源码Share

可以点击这里下载:http://www.baidufe.com/upload/67901343628004.rar


ChangeLog:

2010-4:

   1、初版


2012-07-30:

   1、修复qext.LocalStorage.set方法对expires的支持


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值