HTML5 LocalStorage 本地存储的用法

本地存储变量b的值:

localStorage.setItem("b","isaac");

本地获取变量b的值:

localStorage.getItem("b");

本地清除b的值:

localStorage.removeItem("b");

另外,目前javascript使用非常多的json格式,如果希望存储在本地,可以直接调用JSON.stringify()将其转为字符串。读取出来后调用JSON.parse()将字符串转为json格式,如下所示:

var details = {author:"isaac","description":"fresheggs","rating":100};
storage.setItem("details",JSON.stringify(details));
details = JSON.parse(storage.getItem("details"));

即使是存储cookie,可以直接调用JSON.stringify()将其转为字符串。读取出来后调用JSON.parse()将字符串转为json格式,(如果不转换会报错以至于无法获取值)如下所示:

var details = {author:"isaac","description":"fresheggs","rating":100};
$.cookie("details",JSON.stringify(details));
details = JSON.parse($.cooki("details"));

本地化存储(localStorage) 组件:

/*!
 * 本地化存储(localStorage) 组件
 *
 * 版权所有(C) 2013 马超 (zjcn5205@yeah.net)
 *
 * 这一程序是*软件,你可以遵照*软件基金会出版的GNU通用公共许可证条款来修改和重新发布
 * 这一程序。或者用许可证的第二版,或者(根据你的选择)用任何更新的版本。
 * 发布这一程序的目的是希望它有用,但没有任何担保。甚至没有适合特定目的的隐含的担保。更详细
 * 的情况请参阅GNU通用公共许可证。
 * 你应该已经和程序一起收到一份GNU通用公共许可证的副本。如果还没有,写信给:
 * The Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA02139, USA
 */
/*
 *[功能描述]
 * 给不支持本地存储的浏览器创建一个 window.localStorage 对象来提供类似接口
 * 该对象支持以下方法或属性
    setItem : function(key, value)
    getItem : function(key)
    removeItem : function(key)
    clear : function()
    length : int
    key : function(i)
    isVirtualObject : true
 * 二次包装的接口 window.LS 提供以下方法和属性(如果有jQuery则同样会扩展该对象),推荐使用
    set : function(key, vlaue)
    get : function(key)
    remove : function(key)
    clear : function()
    each : function(callback) callback接受两个参数 key 和 value
    obj : function() 返回一个对象描述的localStorage副本
    length : int
 *
 *[已知问题、使用限制]
 * 原生本地存储的key是区分大小写的,模拟对象不区分(因为userData不区分key的大小写)
 * 模拟对象的 clear 方法仅仅能清理通过本组件设定的数据
 * 模拟对象的实际的存储容量跟原生本地存储有差异
 * 模拟对象不支持任何localStorage事件件
 *
 *[更新日志]
 * 2012-06-20 马超 创建
 * 2012-06-27 马超 增加clear相关方法和属性
 * 2012-07-02 马超 修改节点存储方式
 * 2012-07-03 马超 增加二次包装以优化接口使用
 * 2012-07-04 马超 修改内部逻辑,取消原有的单独存储key的方案,修改查询不存在key的时候的默认值为undefined
 * 2012-07-05 马超 增加二次包装的obj方法
 * 2013-03-06 胡志明 基于瑞星的刘瑞明提供的方案,兼容360急速浏览器IE模式(IE6),降低浏览器自带localStorage优先级,优先使用userData。
 * 2013-03-11 胡志明 恢复iframe代理创建head标签用户存储数据,修正了userData无法垮目录读写问题
 * 2013-03-14 胡志明 对部分无法创建iframe代理的浏览器尝试使用自带localStorage,如果不自带则暂时不支持本地存储
 * 2013-03-18 马超 优化加载判断逻辑和代码,以最大限度保证组件可用
 * 2013-04-23 马超 增加更多的错误处理,进一步提高浏览器的兼容性
 * 2013-05-04 马超 增加对userData的key的无效字符的转义处理功能
 * 2013-06-06 马超 优先探测本地存储,解决IE9下userData使用问题(刷新页面后无效)
 */
(function(window){
    //准备模拟对象、空函数等
    var LS, noop = function(){}, document = window.document, notSupport = {set:noop,get:noop,remove:noop,clear:noop,each:noop,obj:noop,length:0};
    
    //优先探测userData是否支持,如果支持,则直接使用userData,而不使用localStorage
    //以防止IE浏览器关闭localStorage功能或提高安全级别(*_* 万恶的IE)
    //万恶的IE9(9.0.11)),使用userData也会出现类似seesion一样的效果,刷新页面后设置的东西就没有了...
    //只好优先探测本地存储,不能用再尝试使用userData
    (function(){
        // 先探测本地存储 2013-06-06 马超
        // 尝试访问本地存储,如果访问被拒绝,则继续尝试用userData,注: "localStorage" in window 却不会返回权限错误
        // 防止IE10早期版本安全设置有问题导致的脚本访问权限错误
        if( "localStorage" in window ){
            try{
                LS = window.localStorage;
                return;
            }catch(e){
                //如果报错,说明浏览器已经关闭了本地存储或者提高了安全级别
                //则尝试使用userData
            }
        }
        
        //继续探测userData
        var o = document.getElementsByTagName("head")[0], hostKey = window.location.hostname || "localStorage", d = new Date(), doc, agent;
        
        //typeof o.addBehavior 在IE6下是object,在IE10下是function,因此这里直接用!判断
        //如果不支持userData则跳出使用原生localStorage,如果原生localStorage报错,则放弃本地存储
        if(!o.addBehavior){
            try{
                LS = window.localStorage;
            }catch(e){
                LS = null;
            }
            return;
        }
        
        try{ //尝试创建iframe代理,以解决跨目录存储的问题
            agent = new ActiveXObject('htmlfile');
            agent.open();
            agent.write('<s' + 'cript>document.w=window;</s' + 'cript><iframe src="/favicon.ico"></iframe>');
            agent.close();
            doc = agent.w.frames[0].document;
            //这里通过代理document创建head,可以使存储数据垮文件夹访问
            o = doc.createElement('head');
            doc.appendChild(o);
        }catch(e){
            //不处理跨路径问题,直接使用当前页面元素处理
            //不能跨路径存储,也能满足多数的本地存储需求
            //2013-03-15 马超
            o = document.getElementsByTagName("head")[0];
        }
        
        //初始化userData
        try{
            d.setDate(d.getDate() + 36500);
            o.addBehavior("#default#userData");
            o.expires = d.toUTCString();
            o.load(hostKey);
            o.save(hostKey);
        }catch(e){
            //防止部分外壳浏览器的bug出现导致后续js无法运行
            //如果有错,放弃本地存储
            //2013-04-23 马超 增加
            return;
        }
        //开始处理userData
        //以下代码感谢瑞星的刘瑞明友情支持,做了大量的兼容测试和修改
        //并处理了userData设置的key不能以数字开头的问题
        var root, attrs;
        try{
            root = o.XMLDocument.documentElement;
            attrs = root.attributes;
        }catch(e){
            //防止部分外壳浏览器的bug出现导致后续js无法运行
            //如果有错,放弃本地存储
            //2013-04-23 马超 增加
            return;
        }
        var prefix = "p__hack_", spfix = "m-_-c",
            reg1 = new RegExp("^"+prefix),
            reg2 = new RegExp(spfix,"g"),
            encode = function(key){ return encodeURIComponent(prefix + key).replace(/%/g, spfix); },
            decode = function(key){ return decodeURIComponent(key.replace(reg2, "%")).replace(reg1,""); };
        //创建模拟对象
        LS= {
            length: attrs.length,
            isVirtualObject: true,
            getItem: function(key){
                //IE9中 通过o.getAttribute(name);取不到值,所以才用了下面比较复杂的方法。
                return (attrs.getNamedItem( encode(key) ) || {nodeValue: null}).nodeValue||root.getAttribute(encode(key));
            },
            setItem: function(key, value){
                //IE9中无法通过 o.setAttribute(name, value); 设置#userData值,而用下面的方法却可以。
                try{
                    root.setAttribute( encode(key), value);
                    o.save(hostKey);
                    this.length = attrs.length;
                }catch(e){//这里IE9经常报没权限错误,但是不影响数据存储
                }
            },
            removeItem: function(key){
                //IE9中无法通过 o.removeAttribute(name); 删除#userData值,而用下面的方法却可以。
                try{
                    root.removeAttribute( encode(key) );
                    o.save(hostKey);
                    this.length = attrs.length;
                }catch(e){//这里IE9经常报没权限错误,但是不影响数据存储
                }
            },
            clear: function(){
                while(attrs.length){
                    this.removeItem( attrs[0].nodeName );
                }
                this.length = 0;
            },
            key: function(i){
                return attrs[i] ? decode(attrs[i].nodeName) : undefined;
            }
        };
        //提供模拟的"localStorage"接口
        if( !("localStorage" in window) ){
            window.localStorage = LS;            
        }
    })();
    
    //二次包装接口
    window.LS = !LS ? notSupport : {
        set : function(key, value){
            //fixed iPhone/iPad 'QUOTA_EXCEEDED_ERR' bug
            if( this.get(key) !== undefined )
                this.remove(key);
            LS.setItem(key, value);
            this.length = LS.length;
        },
        //查询不存在的key时,有的浏览器返回null,这里统一返回undefined
        get : function(key){
            var v = LS.getItem(key);
            return v === null ? undefined : v;
        },
        remove : function(key){ LS.removeItem(key);this.length = LS.length; },
        clear : function(){ LS.clear();this.length = 0; },
        //本地存储数据遍历,callback接受两个参数 key 和 value,如果返回false则终止遍历
        each : function(callback){
            var list = this.obj(), fn = callback || function(){}, key;
            for(key in list)
                if( fn.call(this, key, this.get(key)) === false ){
                    break;                    
                }
        },
        //返回一个对象描述的localStorage副本
        obj : function(){
            var list={}, i=0, n, key;
            if( LS.isVirtualObject ){
                list = LS.key(-1);
            }else{
                n = LS.length;
                for(; i<n; i++){
                    key = LS.key(i);
                    list[key] = this.get(key);
                }
            }
            return list;
        },
        length : LS.length
    };
    //如果有jQuery,则同样扩展到jQuery
    if( window.jQuery ) window.jQuery.LS = window.LS;
})(window);

使用方法:

存储方法:

$.LS.set('username', app.username);

获取方法:

$.LS.get('username');

清空方法:

$.LS.remove("username");

将所有的字段存储到一个对象中的需要二次封装:

/**
 * 本地存储相关方法对象
 * @type {Object}
 */

var app = app || {};
app.ls = app.ls || {};
(function(){
    var ls = app.ls;
    
  /**
   * 设置本地存储变量的值
   *
   * 如果有keys和val则先设置app.storage里面的对应内容;
   * 然后再把app.sotrage转换成string
   * 最后存入localstorage里面
   *
   * @param {string} keys 定义一个本地存储变量
   * @param {*} val  给keys变量赋予的值
   * @return {[type]} [description]
   */
    ls.set = function(keys, val){
        app.storage[keys] = val;
        var v = xue.json.stringify(app.storage);
        $.LS.set('app', v);
    };
    
  /**
   * 获取本地存储变量的值
   *
   * 先从localstorage里面取出app的内容
   * 把取出的内容转换成JSON
   * 如果有keys返回出对应值,否则返回这个json内容
   *
   * @param  {string} keys 本地存储的一个变量
   * @return {*}           返回本地存储中某个变量的值
   */
    ls.get = function(keys){
        var v = $.LS.get('app');
        var val = xue.json.parse(v);
        if(keys && val[keys]){
            return val[keys];
        }else{
            return val;
        }
    };

/**
   * 删除本地存储的某个元素及其值
   * @param  {string} keys 本地存储的一个变量
   * @return {[type]}      [description]
   */
    ls.remove = function(keys){
        var v = $.LS.get('app');
        if(typeof v != 'string'){
            return;
        }
        var val = xue.json.parse(v);
        if(keys && val[keys]){
            app.storage[keys] = null;
            delete val[keys];
            $.LS.set('app', xue.json.stringify(val));
        }else{
            $.each(app.storage, function(k, m){
                app.storage[k] = null;
            });
            $.LS.remove('app');
        }
    };
})();

使用方法:

存储方法:

app.ls.set('username', app.username);
app.ls.set('userinfo', d.data.userInfo);

获取方法:

app.ls.get('username');

清空方法:

app.ls.remove();或者app.ls.remove('username');

上一篇:关于PHP函数time() date() 和 strtotime() 的时区问题


下一篇:bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题