常用浏览器本地存储的几种方案对比

 

有时需要将网页中的一些数据保存在浏览器端,这样做的好处是,当下次访问页面时,不需要再次向服务器请求数据,直接就可以从本地读取数据。目前常用的有以下几种方法:

cookie

cookie会随着每次HTTP请求头信息一起发送,无形中增加了网络流量,另外,cookie能存储的数据容量有限,根据浏览器类型不同而不同,IE6大约只能存储2K。

Flash ShareObject

这种方式能能解决上面提到的cookie存储的两个弊端,而且能够跨浏览器,应该说是目前最好的本地存储方案。不过,需要在页面中插入一个Flash,当浏览器没有安装Flash控件时就不能用了。所幸的是,没有安装Flash的用户极少。

缺点:需要安装Flash插件。

Google Gear

Google开发出的一种本地存储技术。

缺点:需要安装Gear组件。

userData

IE浏览器可以使用userData来存储数据,容量可达到640K,这种方案是很可靠的,不需要安装额外的插件。缺点:它仅在IE下有效。

sessionStorage

使用于Firefox2+的火狐浏览器,用这种方式存储的数据仅窗口级别有效,同一个窗口(或者Tab)页面刷新或者跳转,都能获取到本地存储的数据,当新开窗口或者页面时,原来的数据就失效了。

缺点:IE不支持、不能实现数据的持久保存。

globalStorage

使用于Firefox2+的火狐浏览器,类似于IE的userData。

//赋值
globalStorage[location.hostname]['name'] = 'tugai';
//读取
globalStorage[location.hostname]['name'];
//删除
globalStorage[location.hostname].removeItem('name');

缺点:IE不支持。

localStorage

localStorage是Web Storage互联网存储规范中的一部分,现在在Firefox 3.5、Safari 4和IE8中得到支持。

缺点:低版本浏览器不支持。

结论:
Flash shareobject是不错的选择,如果你不想在页面上嵌入Flash,可以结合使用userData(IE6+)和globalStorage(Firefox2+)和localStorage(chrome3+)实现跨浏览器。

补充:由于项目需要,简单模拟了HTML5 localStorage中的几个方法,支持firefox2+,IE5+,chrome3+,其他不详。

if (!('localStorage' in window)) {
window.localStorage = (function() {
var documentElement, isIE = !!document.all;
if (isIE) {
documentElement = document.documentElement;
documentElement.addBehavior('#default#userdata');
}
    
return {
setItem: function(key, value) {
if (isIE) {
documentElement.setAttribute('value', value);
documentElement.save(key);
}
else {
window.globalStorage[location.hostname][key] = value;
}
},
getItem: function(key) {
if (isIE) {
documentElement.load(key);
return documentElement.getAttribute('value');
}
return window.globalStorage[location.hostname][key];
},
removeItem: function(key) {
if (isIE) {
documentElement.removeAttribute('value');
documentElement.save(key);
}
else {
window.globalStorage[location.hostname].removeItem(key);
    
}
    
}  
};  
})();
}
   
//写入  
localStorage.setItem('name', 'shuiniuer'); 
//读取 
localStorage.getItem('name'); 
//删除  
localStorage.removeItem('name');

封装了一个插件

/**
 * 客户端的本地存储组件.
 * 
 * 注意:当客户端发起HTTP请求时,存储的数据,不会传递给服务器端,和Cookie不同.
 * 
 * 》使用到的技术特性:
 * 1. localStorage(支持:IE8+、FF3.5+、Chrome4+、Safari4+、Opera10.5+)
 * 2. sessionStorage(支持:IE8+、FF3.5+、Chrome4+、Safari4+、Opera10.5+)
 * 3. userData,IE专有特性,最大存储容量为640K(在IE6、IE7下使用)
 * 
 * 》持久存储API:
 * var Local = require('storage').Local;
 * 1. Local.read(name)        // 读取
 * 2. Local.save(name, value) // 保存
 * 3. Local.remove(name)      // 删除
 * 
 var __newVar__20130529151132107000 = ;
 * 》会话存储API(关闭浏览器后,数据自动删除):__newVar__20130529151132107000
 * var Session = require('storage').Session;
 * 1. Session.read(name)        // 读取
 * 2. Session.save(name, value) // 保存
 * 3. Session.remove(name)      // 删除
 * 
 * @author 水牛儿
 * @version 2013/5/28
 */
define(function(require, exports, module){
               
    var $ = require('jquery');
               
    // IE UserData特性
    var UserData = function(sname){
        this.sname = sname;
        this.tname = sname + '_names';
                   
        this.isSession = sname.split('_')[0] === 'session';
                   
        this.init();
    };
    UserData.prototype = {
        init: function(){
            if (this.isSession) {
                this.names = this.getItem(this.tname) || '';
                           
                this.restore();
            }
        },
                   
        eStore: function(){
            return $('<span class="jxc-ie-userdata"/>').appendTo(document.body)[0];
        }(),
                   
        getItem: function(name){
            this.eStore.load(this.sname);
            return this.eStore.getAttribute(name);
        },
                   
        setItem: function(name, value){
            this.addName(name);
                       
            this.eStore.expires = getUTCString('3y');
            this.eStore.setAttribute(name, value);
            this.eStore.save(this.sname);
        },
                   
        removeItem: function(name){
            this.delName(name);
                       
            this.eStore.removeAttribute(name);
            this.eStore.save(this.sname);
        },
                   
        // 临时存储,要想刷新页面,不清除数据,那么每条数据都必须重新设置下
        // 直接改过期日期还不行,我x,太变态了,why?
        restore: function(){
            if (this.names) {
                var names  = this.names.split(' '),
                    eStore = this.eStore;
                           
                eStore.load(this.sname);
                           
                eStore.expires = getUTCString('3y');
                           
                for (var i = 0, name; name = names[i]; i++) {
                    eStore.setAttribute(name, eStore.getAttribute(name));
                }
                           
                eStore.save(this.sname);
            }
        },
                   
        addName: function(name){
            if (this.isSession) {
                name += ' ';
                           
                if (this.names.indexOf(name) < 0) {
                    this.names += name;
                               
                    this.eStore.setAttribute(this.tname, this.names);
                }
            }
        },
                   
        delName: function(name){
            if (this.isSession) {
                this.names = this.names.replace(name + ' ', '');
                           
                this.eStore.setAttribute(this.tname, this.names);
            }
        },
                   
        // 刷新页面时,设置5s作为缓冲时间,这期间完成数据恢复
        // 如果关闭浏览器,5s没有重新打开页面,那么数据就失效了
        clear: function(){
            this.eStore.expires = getUTCString('5s');
            this.eStore.save(this.sname);
        }
    };
               
    /**
     * 持久化存储.
     */
    exports.Local = function(){
        var oStore = window.localStorage;
                   
        if (!oStore) {
            oStore = new UserData('local_' + location.hostname);
        }
                   
        return {
            read:   bind(oStore.getItem, oStore),
            save:   bind(oStore.setItem, oStore),
            remove: bind(oStore.removeItem, oStore)
        };
    }();
               
    /**
     * 临时存储.
     */
    exports.Session = function(){
        var oStore = window.sessionStorage;
                   
        if (!oStore) {
            oStore = new UserData('session_' + location.hostname);
                       
            addUnloadEvent(oStore);
        }
                   
        return {
            read:   bind(oStore.getItem, oStore),
            save:   bind(oStore.setItem, oStore),
            remove: bind(oStore.removeItem, oStore)
        };
    }();
               
    // 绑定函数的this对象
    function bind(fn, context) {
        return function(){
            return fn.apply(context, arguments);
        };
    };
               
    // 窗口关闭时,清除userdata,但刷新不清除
    function addUnloadEvent(oStore) {
        window.attachEvent('onunload', function(){
            window.detachEvent('onunload', arguments.callee);
                       
            oStore.clear();
        });
    };
               
    // expires = number + y|M|d|h|m|s
    // expires = 360d // 360天
    function getUTCString(expires) {
        expires += '';
                   
        var a = /([^yMdhms]+)(\w)?/.exec(expires),
            n = a ? a[1] : 0,
            f = a ? a[2] : 'y';
                   
        switch (f) {
            case 'y': n*=365*24*3600*1000; break;
            case 'M': n*=30*24*3600*1000; break;
            case 'd': n*=24*3600*1000; break;
            case 'h': n*=3600*1000; break;
            case 'm': n*=60*1000; break;
            case 's': n*=1000; break;
            default:  n*=1000; break;
        }
                   
        var d = new Date();
        d.setMilliseconds( d.getMilliseconds() + n );
                   
        return d.toUTCString();
    };
               
});