兼容多浏览器的本地存储

   在做考试系统时需要解决这样一个问题,就是当考生考试时可能出出现断网、关闭浏览器,刷新等问题,数据此时可能没有及时写入数据库,所以造成数据丢失问题,,所以这里就需要用到本地存储,以前的版本都是用cookie,但是不得不说cookie太小了,只有可怜的4k,而机房的网有时候实在是让人捉急,所以,考虑换一种方案。

直接读取XML实现方式

    因为本地存储平时接触的不是太多,开始想的只是简单的读取本地的XML,做起来倒是挺容易的,一个语句就能搞定: 

  1. <script language="javascript"type="text/javascript">  
  2.                   var fso, f1, ts, s;  
  3.          varForReading = 1;  
  4.          fsonew ActiveXObject("Scripting.FileSystemObject");  
  5.          //创建文件  
  6.      f1 =fso.CreateTextFile("F:\\testfile.txt", true);  
  7.          //填写一行数据  
  8.          f1.WriteLine("我是美丽的姑娘");  
  9.          f1.WriteBlankLines(1);  
  10.          //关闭文件  
  11.          f1.Close();  
  12.          //打开文件  
  13.          tsfso.OpenTextFile("F:\\list.xml", ForReading);  
  14.           var nodes = ts.documentElement.childNodes;  
  15.          //读取文件一行内容到字符串  
  16.          sts.ReadLine();  
  17.          //显示字符串信息  
  18.          alert("文件信息是: "+s);  
  19.          //关闭文件  
  20.          ts.Close();  
  21.           
  22. </script>  



 

    但是这样写虽然简单,带来的弊端也不少,于是上网查到UserData可以解决这个问题。

UserData实现方式:

    userData行为通过将数据写入一个UserData存储区(UserDatastore)来保存数据,userData可以将数据以XML格式保存在客户端计算机上,如果你用的是 Windows 2000 或者 Windows XP,是保存在C:\Documents and Settings\Liming\UserData\文件夹下(如果操作系统不是安装在C盘,那么C就应该是操作系统所在的分区)。

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

    userData行为提供了一个比Cookie更具有动态性和更大容量的数据结构。每页的UserData存储区数据大小可以达到64 Kb,每个域名可以达到640 Kb。

    userData行为通过sessions为每个对象分配UserData存储区。使用save和load方法将UserData存储区数据保存在缓存(cache)中。一旦UserData存储区保存以后,即使IE浏览器关闭或者刷新了,下一次进入该页面,数据也能够重新载入而不会丢失。

    但是,UserData是IE的东西,所以其他浏览器不兼容,当时,因为现在做的这个考试系统一般情况下都在UserData下使用,所以也实现了一下:

 

[html] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. <HTML>  
  2. <HEAD>  
  3. <STYLE>  
  4. .userData{behavior:url(#default#userdata);}  
  5. </STYLE>  
  6. <SCRIPT>  
  7. function fnSaveInput(){  
  8. var oPersist=oPersistForm.oPersistInput;  
  9. oPersist.setAttribute("sPersist",oPersist.value);//将oPersist.value存储为sPersist属性  
  10. oPersist.save("oXMLBranch"); //存储在名为oXMLBranch的UserData存储区  
  11. }  
  12. function fnLoadInput(){  
  13. var oPersist=oPersistForm.oPersistInput;  
  14.  varabc=oPersist.load("oXMLBranch"); //载入在名为oXMLBranch的UserData存储区  
  15. oPersist.value=oPersist.getAttribute("sPersist");//将sPersist属性赋值给oPersist.value  
  16. }  
  17. </SCRIPT>  
  18. </HEAD>  
  19. <BODY>  
  20. <FORM ID="oPersistForm">  
  21. <INPUT CLASS="userData"TYPE="text" ID="oPersistInput">  
  22. <INPUT TYPE="button"VALUE="Load" onclick="fnLoadInput()">  
  23. <INPUT TYPE="button"VALUE="Save" onclick="fnSaveInput()">  
  24. </FORM>  
  25. </BODY>  
  26. </HTML>  



 

HTML5 LocalStorage   

    但是,毕竟UserData有他的局限性,处于兼容考虑,也在实现过程中听说了一种叫HTML5 LocalStorage 的东西。

要介绍HTML5 LocalStorage,首先介绍一下本地存储的历史:


 

    从这里可以看出去,本地存储一路从Cookies走到最后,真心的不容易,那么,HTML5 LocalStorage 具体有什么好处呢?

    最早的Cookies自然是大家都知道,问题主要就是太小,大概也就4KB的样子,而且IE6只支持每个域名20个cookies,太少了。优势就是大家都支持,而且支持得还蛮好。很早以前那些禁用cookies的用户也都慢慢的不存在了,就好像以前禁用javascript的用户不存在了一样。

    userData是IE的东西。现在用的最多的是Flash,空间是Cookie的25倍,基本够用。再之后Google推出了Gears,虽然没有限制,但不爽的地方就是要装额外的插件。到了HTML5把这些都统一了,官方建议是每个网站5MB,非常大了,就存些字符串,足够了。比较诡异的是居然所有支持的浏览器目前都采用的5MB,尽管有一些浏览器可以让用户设置,但对于网页制作者来说,目前的形势就5MB来考虑是比较妥当的。

    那么,有哪些浏览器支持他呢?


 

    所以根据图我们可以看出,技术所以的浏览器都支持HTML5 LocalStorage,所以,这也让本地存储前途一片光明啊!

    下面写一个简单的实例: 

  1. <body>  
  2. <p>You have viewed this page <spanidspanid="count">0</span> time(s).</p>  
  3. <p><input type="button"value="changeStorage" onClick="changeS()"/></p>  
  4. <script>  
  5.          varstorage = window.localStorage;  
  6.           
  7.          if(!storage.getItem("pageLoadCount"))storage.setItem("pageLoadCount",0);  
  8.                    storage.pageLoadCountparseInt(storage.getItem("pageLoadCount")) + 1;//必须格式转换  
  9.                    document.getElementById("count").innerHTMLstorage.pageLoadCount;  
  10.                    showStorage();  
  11.                    if(window.addEventListener){  
  12.                     window.addEventListener("storage",handle_storage,false);  
  13.                    }elseif(window.attachEvent){  
  14.                     window.attachEvent("onstorage",handle_storage);  
  15.          }  
  16.           
  17.          functionhandle_storage(e){  
  18.                     if(!e){e=window.event;}  
  19.                     showObject(e);  
  20.          }  
  21.           
  22.          functionshowObject(obj){  
  23.                     //递归显示object  
  24.                     if(!obj){return;}  
  25.                              for(var i in obj){  
  26.                               if(typeof(obj[i])!="object" ||obj[i]==null){  
  27.                                  document.write(i+ " : " + obj[i] + "<br/>");  
  28.                               }   else{  
  29.                                  document.write(i+ " : object" + "<br/>");  
  30.                               }  
  31.                     }  
  32.          }  
  33.           
  34.          storage.setItem("a",5);  
  35.           
  36.          functionchangeS(){  
  37.                     //修改一个键值,测试storage事件  
  38.                     if(!storage.getItem("b")){storage.setItem("b",0);}  
  39.                            storage.setItem('b',parseInt(storage.getItem('b'))+1);  
  40.          }  
  41.           
  42.          functionshowStorage(){  
  43.                     //循环显示localStorage里的键值对  
  44.                     for(var i=0;i<storage.length;i++){  
  45.                               //key(i)获得相应的键,再用getItem()方法获得对应的值  
  46.                               document.write(storage.key(i)+ " :" + storage.getItem(storage.key(i)) + "<br>");  
  47.                     }  
  48.          }  
  49. </script>  
  50. </body>  



 

    当运行这个实例的时候,出现一个诡异的问题,就是其他浏览器还好,在IE下报错,所以,这也算是他的一个特点吧,它在IE、Firefox测试的时候需要把文件上传到服务器上(或者localhost),直接点开本地的HTML文件,是不行的,这里一定要注意。

    最后,这些demo都有了,我们详细的讲一下它的一些属性:


 

    到这里,基本上基本的概念和简单的demo就都清楚了,现在需要的就是把这些东西整合到一起,因为我们知道HTML5 LocalStorage不能支持IE8以下的浏览器,但是考试系统运行的环境大部分都在IE8以下,所以我们如果想做一个兼容性比较好的本地存储,就需要UserData和HTML5 LocalStorage连起来用,皇天不负有心人,在实现的过程中,我在网上找到了这样好的代码,毕竟以实现程序为主,又好使的,还是用用好使的吧。下面是代码:

我是借鉴的代码哦

    但是这个文章里没有对命名空间给出代码,所以直接使用是有问题的,需要加入命名空间的代码,以下是我稍微改动了一下,并且适应于考试系统的代码:

完整的demo

    HTML代码(注意,一定要放在服务器上运行,IIS,TOMCAL,JBOSS都可以,不要直接点击运行): 

  1. <!DOCTYPE html PUBLIC "-//W3C//DTDXHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  2. <htmlxmlnshtmlxmlns="http://www.w3.org/1999/xhtml">  
  3. <head>  
  4. <metahttp-equivmetahttp-equiv="Content-Type" content="text/html;charset=gb2312" />  
  5.    
  6. <title>无标题文档</title>  
  7.  <script type="text/javascript"src="js/jquery-1.4.2.min.js"></script>  
  8.    <script type="text/javascript" src="js/jquery.utils.js"></script>  
  9.  <script type="text/javascript"src="js/localstorage.js"></script>  
  10.    
  11.    
  12. <script>  
  13. function saveStu(){  
  14.          qext.LocalStorage.save("2344234","234","234234","234234");  
  15. }  
  16.    
  17.  function saveMore(){  
  18. // 保存多个对象  
  19. qext.LocalStorage.set([{  
  20.   key : "username",  
  21.   value : "{  ‘sitename’: ‘K JSON’, ‘siteurl’: ‘www.kjson.com’, ‘keyword’: ‘JSON在线校验,格式化JSON,json 在线校验’}",  
  22.    
  23.   expires : 3600 * 1000  /*单位:ms*/  
  24. },{  
  25.   key : "password",  
  26.   value : "zxlie",  
  27.   expires : 3600 * 1000  /*单位:ms*/  
  28. }]);  
  29. }   
  30. function show(){  
  31.          //获取某一个本地存储,返回值为:{key:"",value:"",expires:""},未取到值时返回值为:null  
  32.  varrst = qext.LocalStorage.get({  
  33.    key : "2344234234234234"  
  34.  });  
  35.  alert(rst);  
  36. }  
  37. function getMore(){  
  38.          vararrGet = qext.LocalStorage.getAllKeys();  
  39.          for(vari=0;i<arrGet.length;i++){  
  40.                    varrst = qext.LocalStorage.get({  
  41.                        key : arrGet[i]  
  42.                     });  
  43.                     alert(rst);  
  44.          }  
  45. }  
  46. function removeOne(){  
  47.          qext.LocalStorage.remove({  
  48.                     key : "2344234234234"  
  49.          })  
  50. }  
  51.    
  52. </script>  
  53. </head>  
  54.    
  55. <body>  
  56. <input type="button"onclick="saveStu()" value="保存数据" />  
  57. <input type="button"onclick="show()" value="显示数据" />  
  58. <input type="button"onclick="getMore()" value="显示全部数据" />  
  59. <input type="button"onclick="removeOne()" value="移除一个数据" />  
  60. </body>  
  61. </html>  



 

JS代码: 

  1. /**  
  2.  * 注册命名空间  
  3.  *@param {String} fullNS 完整的命名空间字符串,如qui.dialog  
  4.  *@param {Boolean} isIgnorSelf 是否忽略自己,默认为false,不忽略  
  5.  *@author   
  6.  *@example  
  7.  *     window.registNS("QingFeed.Text.Bold");  
  8.  */  
  9. window.registNS =function(fullNS,isIgnorSelf){  
  10.    //命名空间合法性校验依据  
  11.    var reg = /^[_$a-z]+[_$a-z0-9]*/i;  
  12.           
  13.    // 将命名空间切成N部分, 比如baidu.libs.Firefox等  
  14.    var nsArray = fullNS.split('.');  
  15.    var sEval = "";  
  16.    var sNS = "";  
  17.    var n = isIgnorSelf ? nsArray.length - 1 : nsArray.length;  
  18.    for (var i = 0; i < n; i++){  
  19.        //命名空间合法性校验  
  20.         if(!reg.test(nsArray[i])) {  
  21.            throw new Error("Invalid namespace:" + nsArray[i] +"");  
  22.            return ;  
  23.        }  
  24.        if (i != 0) sNS += ".";  
  25.        sNS += nsArray[i];  
  26.        // 依次创建构造命名空间对象(假如不存在的话)的语句  
  27.        sEval += "if(typeof(" + sNS + ")=='undefined') " +sNS + "=new Object();else " + sNS + ";";  
  28.     }  
  29.    //生成命名空间  
  30.    if (sEval != "") {  
  31.        return eval(sEval);  
  32.     }  
  33.    return {};  
  34. };  
  35.    
  36.    
  37. /**  
  38.  * 注册命名空间  
  39.  */  
  40. window.registNS('qext');  
  41.    
  42. /**  
  43.  *@class qext.LocalStorage  
  44.  * 跨浏览器的本地存储实现。高级浏览器使用localstorage,ie使用UserData。虽然说是本地存储,也请不要存储过大数据,最好不要大于64K.  
  45.  * 因为ie下UserData每页最大存储是64k。  
  46.  *@singleton  
  47.  *@author zhaoxianlie (xianliezhao@foxmail.com)  
  48.  */  
  49. (function(){  
  50.    /**  
  51.     * 验证字符串是否合法的键名  
  52.     * @param {Object} key 待验证的key  
  53.     * @return {Boolean} true:合法,false:不合法  
  54.     * @private  
  55.     */  
  56.    function _isValidKey(key) {  
  57.        return (newRegExp("^[^\\x00-\\x20\\x7f\\(\\)<>@,;:\\\\\\\"\\[\\]\\?=\\{\\}\\/\\u0080-\\uffff]+\x24")).test(key);  
  58.     }  
  59.      
  60.    //所有的key  
  61.    var _clearAllKey = "_baidu.ALL.KEY_";  
  62.      
  63.    /**  
  64.     * 创建并获取这个input:hidden实例  
  65.     * @return {HTMLInputElement} input:hidden实例  
  66.     * @private  
  67.     */  
  68.    function _getInstance(){  
  69.        //把UserData绑定到input:hidden上  
  70.        var _input = null;  
  71.        //是的,不要惊讶,这里每次都会创建一个input:hidden并增加到DOM树种  
  72.        //目的是避免数据被重复写入,提早造成“磁盘空间写满”的Exception  
  73.        _input = document.createElement("input");  
  74.        _input.type = "hidden";  
  75.        _input.addBehavior("#default#userData");  
  76.        document.body.appendChild(_input);  
  77.        return _input;  
  78.     }  
  79.      
  80.    /**  
  81.     * 将数据通过UserData的方式保存到本地,文件名为:文件名为:config.key[1].xml  
  82.     * @param {String} key 待存储数据的key,和config参数中的key是一样的  
  83.     * @param {Object} config 待存储数据相关配置  
  84.     * @cofnig {String} key 待存储数据的key  
  85.     * @config {String} value 待存储数据的内容  
  86.     * @config {String|Object} [expires] 数据的过期时间,可以是数字,单位是毫秒;也可以是日期对象,表示过期时间  
  87.     * @private  
  88.     */  
  89.    function __setItem(key,config){  
  90.        try {  
  91.            var input = _getInstance();  
  92.            //创建一个Storage对象  
  93.            var storageInfo = config || {};  
  94.            //设置过期时间  
  95.            if(storageInfo.expires) {  
  96.                 var expires;  
  97.                 //如果设置项里的expires为数字,则表示数据的能存活的毫秒数  
  98.                 if ('number' == typeofstorageInfo.expires) {  
  99.                    expires = new Date();  
  100.                    expires.setTime(expires.getTime() + storageInfo.expires);  
  101.                 }  
  102.                 input.expires =expires.toUTCString();  
  103.            }  
  104.              
  105.            //存储数据  
  106.            input.setAttribute(storageInfo.key,storageInfo.value);  
  107.            //存储到本地文件,文件名为:storageInfo.key[1].xml  
  108.            input.save(storageInfo.key);  
  109.        } catch (e) {  
  110.        }  
  111.     }  
  112.    
  113.    /**  
  114.     * 将数据通过UserData的方式保存到本地,文件名为:文件名为:config.key[1].xml  
  115.     * @param {String} key 待存储数据的key,和config参数中的key是一样的  
  116.     * @param {Object} config 待存储数据相关配置  
  117.     * @cofnig {String} key 待存储数据的key  
  118.     * @config {String} value 待存储数据的内容  
  119.     * @config {String|Object} [expires] 数据的过期时间,可以是数字,单位是毫秒;也可以是日期对象,表示过期时间  
  120.     * @private  
  121.     */  
  122.    function _setItem(key,config){  
  123.        //保存有效内容  
  124.        __setItem(key,config);  
  125.          
  126.        //下面的代码用来记录当前保存的key,便于以后clearAll  
  127.        var result = _getItem({key : _clearAllKey});  
  128.        if(result) {  
  129.            result = {  
  130.                key : _clearAllKey,  
  131.                 value : result  
  132.            };  
  133.        } else {  
  134.            result = {  
  135.                 key : _clearAllKey,  
  136.                 value : ""  
  137.            };  
  138.        }  
  139.          
  140.        if(!(new RegExp("(^|\\|)" + key + "(\\||$)",'g')).test(result.value)){  
  141.            result.value += "|" + key;  
  142.            //保存键  
  143.            __setItem(_clearAllKey,result);      
  144.        }  
  145.     }  
  146.      
  147.    /**  
  148.     * 提取本地存储的数据  
  149.     * @param {String} config 待获取的存储数据相关配置  
  150.     * @cofnig {String} key 待获取的数据的key  
  151.     * @return {String} 本地存储的数据,获取不到时返回null  
  152.     * @example  
  153.     * qext.LocalStorage.get({  
  154.     *      key : "username"  
  155.     * });  
  156.     * @private  
  157.     */  
  158.    function _getItem(config){  
  159.        try {  
  160.            var input = _getInstance();  
  161.            //载入本地文件,文件名为:config.key[1].xml  
  162.            input.load(config.key);  
  163.            //取得数据  
  164.            return input.getAttribute(config.key) || null;  
  165.        } catch (e) {  
  166.            return null;             
  167.        }  
  168.     }  
  169.      
  170.    /**  
  171.     * 移除某项存储数据  
  172.     * @param {Object} config 配置参数  
  173.     * @cofnig {String} key 待存储数据的key  
  174.     * @private  
  175.     */  
  176.    function _removeItem(config){  
  177.                    try{  
  178.                             varinput = _getInstance();  
  179.                             //载入存储区块  
  180.                             input.load(config.key);  
  181.                             //移除配置项  
  182.                             input.removeAttribute(config.key);  
  183.                             //强制使其过期  
  184.                             varexpires = new Date();  
  185.                             expires.setTime(expires.getTime()- 1);  
  186.                             input.expiresexpires.toUTCString();  
  187.                             input.save(config.key);  
  188.                              
  189.                             //从allkey中删除当前key                        
  190.                             //下面的代码用来记录当前保存的key,便于以后clearAll  
  191.                             var result = _getItem({key :_clearAllKey});  
  192.                             if(result){  
  193.                                      resultresult.replace(new RegExp("(^|\\|)" + config.key +"(\\||$)",'g'),'');  
  194.                                      result= {  
  195.                                                key: _clearAllKey,  
  196.                                                value: result  
  197.                                      };  
  198.                                      //保存键  
  199.                                      __setItem(_clearAllKey,result);        
  200.                             }  
  201.                              
  202.                    }catch (e) {  
  203.                    }  
  204.          }  
  205.      
  206.    //移除所有的本地数据  
  207.    function _clearAll(){  
  208.        result = _getItem({key : _clearAllKey});  
  209.        if(result) {  
  210.            var allKeys = result.split("|");  
  211.            var count = allKeys.length;  
  212.            for(var i = 0;i < count;i++){  
  213.                 if(!!allKeys[i]) {  
  214.                    _removeItem({key:allKeys[i]});  
  215.                 }  
  216.            }  
  217.        }  
  218.     }  
  219.      
  220.      
  221.    /**  
  222.     * 获取所有的本地存储数据对应的key  
  223.     * @return {Array} 所有的key  
  224.     * @private  
  225.     */  
  226.    function _getAllKeys(){  
  227.        var result = [];  
  228.        var keys = _getItem({key : _clearAllKey});  
  229.        if(keys) {  
  230.            keys = keys.split('|');  
  231.            for(var i = 0,len = keys.length;i < len;i++){  
  232.                 if(!!keys[i]) {  
  233.                     result.push(keys[i]);  
  234.                 }  
  235.            }  
  236.        }  
  237.        return result ;  
  238.     }  
  239.      
  240.    /**  
  241.     * 判断当前浏览器是否支持本地存储:window.localStorage  
  242.     * @return {Boolean} true:支持;false:不支持  
  243.     * @remark 支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+  
  244.     * @private  
  245.     */  
  246.    var _isSupportLocalStorage = (('localStorage' in window) &&(window['localStorage'] !== null)),  
  247.        _isSupportUserData = !!jQuery.browser.ie;  
  248.      
  249.    qext.LocalStorage = {  
  250.        /**  
  251.         * 如果支持本地存储,返回true;否则返回false  
  252.         * @type Boolean  
  253.         */  
  254.        isAvailable : _isSupportLocalStorage || _isSupportUserData,  
  255.          
  256.        /**  
  257.         * 将数据进行本地存储(只能存储字符串信息)  
  258.         * <pre><code>  
  259.                     * //保存单个对象  
  260.                     * qext.LocalStorage.set({  
  261.                     *             key: "username",  
  262.                     *             value: "baiduie",  
  263.                     *             expires: 3600 * 1000  
  264.                     * });  
  265.                     * //保存对个对象  
  266.                     * qext.LocalStorage.set([{  
  267.                     *             key: "username",  
  268.                     *             value: "baiduie",  
  269.                     *             expires: 3600 * 1000  
  270.                     * },{  
  271.                     *             key: "password",  
  272.                     *             value: "zxlie",  
  273.                     *             expires: 3600 * 1000  
  274.                     * }]);  
  275.         * </code></pre>  
  276.         * @param {Object} obj 待存储数据相关配置,可以是单个JSON对象,也可以是由多个JSON对象组成的数组  
  277.         * <ul>  
  278.         * <li><b>key</b> : String <divclassdivclass="sub-desc">待存储数据的key,务必将key值起的复杂一些,如:baidu.username</div></li>  
  279.         * <li><b>value</b> : String <divclassdivclass="sub-desc">待存储数据的内容</div></li>  
  280.         * <li><b>expires</b> : String/Object (Optional)<divclassdivclass="sub-desc">数据的过期时间,可以是数字,单位是毫秒;也可以是日期对象,表示过期时间</div></li>  
  281.         * </ul>  
  282.         */  
  283.        set : function(obj){  
  284.                             //保存单个对象  
  285.                             var_set_ = function(config){  
  286.                                      //key校验  
  287.                                      if(!_isValidKey(config.key)){return;}  
  288.    
  289.                                      //待存储的数据  
  290.                                      varstorageInfo = config || {};  
  291.                                       
  292.                                      //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+  
  293.                                      if(_isSupportLocalStorage){  
  294.                                                window.localStorage.setItem(storageInfo.key,storageInfo.value);  
  295.                                                if(config.expires){  
  296.                         var expires;  
  297.                         //如果设置项里的expires为数字,则表示数据的能存活的毫秒数  
  298.                         if ('number' == typeofstorageInfo.expires) {  
  299.                             expires = newDate();  
  300.                            expires.setTime(expires.getTime() + storageInfo.expires);  
  301.                         }  
  302.    
  303.                        window.localStorage.setItem(storageInfo.key +".expires",expires);  
  304.                                                }  
  305.                                      }else if(_isSupportUserData) { //IE7及以下版本,采用UserData方式  
  306.                                                _setItem(config.key,storageInfo);  
  307.                                      }         
  308.                             };  
  309.    
  310.                             //判断传入的参数是否为数组  
  311.                             if(obj&& obj.constructor === Array && obj instanceof Array){  
  312.                                      for(vari = 0,len = obj.length;i < len;i++){  
  313.                                                _set_(obj[i]);  
  314.                                      }  
  315.                             }elseif(obj){  
  316.                                      _set_(obj);  
  317.                             }  
  318.        },  
  319.                     
  320.                    /**  
  321.                     * 提取本地存储的数据  
  322.         * <pre><code>  
  323.                     * //获取某一个本地存储,返回值为:{key:"",value:"",expires:""},未取到值时返回值为:null  
  324.                     * var rst = qext.LocalStorage.get({  
  325.                     *             key: "username"  
  326.                     * });  
  327.                     * //获取多个本地存储,返回值为:["","",""],未取到值时返回值为:[null,null,null]  
  328.                     * qext.LocalStorage.get([{  
  329.                     *             key: "username"  
  330.                     * },{  
  331.                     *             key: "password"  
  332.                     * },{  
  333.                     *             key: "sex"  
  334.                     * }]);  
  335.         * </code></pre>  
  336.                     * @param {String} obj 待获取的存储数据相关配置,支持单个对象传入,同样也支持多个对象封装的数组格式  
  337.                     * @config {String} key 待存储数据的key  
  338.                     * @return {String} 本地存储的数据,传入为单个对象时,返回单个对象,获取不到时返回null;传入为数组时,返回为数组  
  339.                     */  
  340.        get : function(obj){  
  341.                             //获取某一个本地存储  
  342.                             var_get_ = function(config){  
  343.                                      //结果       
  344.                                      varresult = null;  
  345.                                      if(typeofconfig === "string") config = {key : config};  
  346.                                      //key校验  
  347.                                      if(!_isValidKey(config.key)){return result;}  
  348.                                       
  349.                                      //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+  
  350.                                      if(_isSupportLocalStorage){  
  351.                                                resultwindow.localStorage.getItem(config.key);  
  352.                                                //过期时间判断,如果过期了,则移除该项  
  353.                                                if(result){  
  354.                                                         varexpires = window.localStorage.getItem(config.key + ".expires");  
  355.                                                         result= {  
  356.                                                                  value: result,  
  357.                                                                  expires: expires ? new Date(expires) : null  
  358.                                                         };  
  359.                                                         if(result&& result.expires && result.expires < new Date()) {  
  360.                                                                  resultnull;  
  361.                                                                  window.localStorage.removeItem(config.key);  
  362.                            window.localStorage.removeItem(config.key + ".expires");  
  363.                                                         }  
  364.                                                }  
  365.                                      }else if(_isSupportUserData) { //IE7及以下版本,采用UserData方式  
  366.                                                //这里不用单独判断其expires,因为UserData本身具有这个判断  
  367.                                                result_getItem(config);  
  368.                                                if(result){  
  369.                                                         result= { value : result };  
  370.                                                }  
  371.                                      }  
  372.                                       
  373.                                      returnresult ? result.value : null;  
  374.                             };  
  375.                              
  376.                             varrst = null;  
  377.                             //判断传入的参数是否为数组  
  378.                             if(obj&& obj.constructor === Array && obj instanceof Array){  
  379.                                      rst= [];  
  380.                                      for(vari = 0,len = obj.length;i < len;i++){  
  381.                                                rst.push(_get_(obj[i]));  
  382.                                      }  
  383.                             }elseif(obj){  
  384.                                      rst_get_(obj);  
  385.                             }  
  386.                             returnrst;  
  387.        },  
  388.          
  389.        /**  
  390.         * 移除某一项本地存储的数据  
  391.         * <pre><code>  
  392.                     * //删除一个本地存储项  
  393.                     * qext.LocalStorage.remove({  
  394.                     *             key: "username"  
  395.                     * });  
  396.                     * //删除多个本地存储项目 *  
  397.                     * qext.LocalStorage.remove([{  
  398.                     *             key: "username"  
  399.                     * },{  
  400.                     *             key: "password"  
  401.                     * },{  
  402.                     *             key: "sex"  
  403.                     * }]);  
  404.         * </code></pre>  
  405.                     * @param {String} obj 待移除的存储数据相关配置,支持移除某一个本地存储,也支持数组形式的批量移除  
  406.                     * @config {String} key 待移除数据的key  
  407.                     * @return 无  
  408.         */  
  409.        remove : function(obj){  
  410.                             //移除某一项本地存储的数据  
  411.                             var_remove_ = function(config){  
  412.                                      //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+  
  413.                                      if(_isSupportLocalStorage){  
  414.                                                window.localStorage.removeItem(config.key);  
  415.                                                window.localStorage.removeItem(config.key+ ".expires");  
  416.                                      }else if(_isSupportUserData){ //IE7及以下版本,采用UserData方式  
  417.                                                _removeItem(config);  
  418.                                      }  
  419.                             };  
  420.                              
  421.                             //判断传入的参数是否为数组  
  422.                             if(obj&& obj.constructor === Array && obj instanceof Array){  
  423.                                      for(vari = 0,len = obj.length;i < len;i++){  
  424.                                                _remove_(obj[i]);  
  425.                                      }  
  426.                             }elseif(obj){  
  427.                                      _remove_(obj);  
  428.                             }  
  429.        },  
  430.          
  431.        /**  
  432.         * 清除所有本地存储的数据  
  433.         * <pre><code>  
  434.         * qext.LocalStorage.clearAll();  
  435.         * </code></pre>  
  436.         */  
  437.        clearAll : function(){  
  438.            //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+  
  439.            if(_isSupportLocalStorage) {  
  440.                 window.localStorage.clear();  
  441.            } else if(_isSupportUserData) { //IE7及以下版本,采用UserData方式  
  442.                 _clearAll();  
  443.            }  
  444.        },  
  445.          
  446.        //保存单个对象到本地  
  447.        save:function(StudentID,ExamID,QuestionID,ExamAnswer){  
  448.        qext.LocalStorage.set({  
  449.           key : StudentID+ExamID+QuestionID,  
  450.           value : "{  StudentID’: ‘"+StudentID+"’,‘ExamID’: ‘"+ExamID+"’, ‘QuestionID’:‘"+QuestionID+"’,‘ExamAnswer’: ‘"+ExamAnswer+"’}",  
  451.           expires : 3600 * 1000  /*单位:ms*/  
  452.        });  
  453.        },  
  454.        /**  
  455.         * 获取所有的本地存储数据对应的key  
  456.         * <pre><code>  
  457.         * var keys = qext.LocalStorage.getAllKeys();  
  458.         * </code></pre>  
  459.         * @return {Array} 所有的key  
  460.         */  
  461.        getAllKeys : function(){  
  462.            var result = [];  
  463.            //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+  
  464.            if(_isSupportLocalStorage) {  
  465.                 var key;  
  466.                 for(var i = 0,len =window.localStorage.length;i < len;i++){  
  467.                     key = window.localStorage.key(i);  
  468.                    if(!/.+\.expires$/.test(key)) {  
  469.                         result.push(key);  
  470.                     }  
  471.                 }  
  472.            } else if(_isSupportUserData) { //IE7及以下版本,采用UserData方式  
  473.                 result = _getAllKeys();  
  474.            }  
  475.              
  476.            return result;  
  477.        }  
  478.    };  
  479.    
  480. })();  



 

挺佩服封装这个代码的人,感觉无论从编程习惯还是代码的质量上都值得每一个人学习,所以,推荐一下。

到此,所有的本地存储的问题都解决了,又是完美的一天!

下面是一个完整的程序:我是完整的程序

参考博客:http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html

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

posted @ 2014-03-19 17:27  web8  阅读(661)  评论(0编辑  收藏  举报