web前端实现本地存储

  当咱们在说起web前端本地存储的时候,首先须要介绍一下本地化存储的概念和历史。本地化存储历来不是一个新奇的概念,由于web应用程序一直在追求的就是媲美甚至超越桌面应用程序。可是桌面应用程序一直优于web应用程序一个很重要的缘由是它的本地化存储获得了很好的支持。对于本地应用程序,操做系统会提供一个抽象层,用于存储和获取特定于应用程序的数据,这些数据能够存储于注册表、INI文件,或者其余什么地方,这取决于操做系统的实现,若是本地应用程序须要不单是键值对形式的本地存储,可使用嵌入式数据库或其余不少种解决方案。而对于web应用程序,它的本地存储一步一步走到今天的HTML5本地存储是很是不容易的。为了描述它的历史,咱们能够先看一张图片:html

Storage-support

  从图片能够看出,不管是从存储数据的大小仍是兼容性来看,web前端本地存储都走得不容易。在着重介绍HTML5本地存储以前,咱们先来看一看前面几个存储方式的概念。前端

  HTTP cookie:HTTP cookie的缺点很明显,最多只能存储4KB的数据,每一个HTTP请求都会被传送回服务器,明文传输(除非你使用SSL)。git

  IE userData:userData是微软在上世纪90年代的浏览器大战时推出的本地存储方案,借助DHTML的behaviour属性来存储本地数据, 容许每一个页面最多存储64K数据,每一个站点最多640K数据,userData的缺点显而易见,它不是Web标准的一部分,除非你的程序只须要支持IE, 不然它基本没什么用处。github

  Flash cookie:Flash cookie的名字有些误导,它实际上和HTTP cookie并非一回事,或许它的名字应该叫作"Flash本地存储”,Flash cookie默认容许每一个站点存储不超过100K的数据,若是超出了,Flash会自动向用户请求更大的存储空间,借助Flash的 ExternalInterface接口,你能够很轻松地经过Javascript操做Flash的本地存储。Flash的问题很简单,就是由于它是 Flash。web

  Google Gears:Gears是Google在07年发布的一个开源浏览器插件,旨在改进各大浏览器的兼容性,Gears内置了一个基于SQLite的嵌入式 SQL数据库,并提供了统一API对数据库进行访问,在取得用户受权以后,每一个站点能够在SQL数据库中存储不限大小的数据,Gears的问题就是 Google本身都已经不用它了。数据库

  从上面的简介咱们能够看出,在之前,本地存储面临的主要问题是,对于存储容量较大的方式,须要特定的插件支持;对于不须要插件支持的存储方式,则处于安全问题或者大小限制而遭到扼杀。在这种双重的矛盾面前,HTML5本地存储横空出世,对于前端开发人员是一种巨大的福音。浏览器

  所谓的HTML5本地存储更精确的说法应该是DOM存储。根据MDN的定义,DOM存储的机制是经过存储字符串类型的键/值对,来提供一种安全的存取方式.这个附加功能的目标是提供一个全面的,能够用来建立交互式应用程序的方法(包括那些高级功能,例如能够离线工做一段时间)。安全

  HTML5的DOM存储分红两种:SessionStorage和LocalStorage。在当代浏览器中的兼容性以下:服务器

     Compatibility

  上图中说起的globalStorage是非标准的,已经废弃,在这里咱们直接忽略它。而sessionStorage和localStorage在绝大部分现代浏览器中已经获得了很好的支持,可是既然是绝大部分,就必须照顾那些还不支持这两个对象的浏览器。为了检测浏览器是否支持这两个对象,咱们能够简单的用下面的代码来检测:cookie

1 function storageSupport() {  
2         try {  
3             return 'localStorage' in window && window['localStorage'] !== null;  
4         } catch (e) {  
5             return false;  
6         }  
7 }

  很是幸运的是,这两种对象的使用方式都很是简单,这里借用网上 的一张图:

  Storage-usage   

  首先咱们来看一看sessionStorage,sessionStorage 是个全局对象,它维护着在页面会话(page session)期间有效的存储空间。只要浏览器开着,页面会话周期就会一直持续。当页面从新载入(reload)或者被恢复(restores)时,页面会话也是一直存在的。每在新标签或者新窗口中打开一个新页面,都会初始化一个新的会话。这句话看起来比较抽象,咱们直接看一个demo:

1 var name = sessionStorage.setItem("myname","yuanzm");
2 alert(sessionStorage.getItem("myname"));

  当咱们在浏览器中打开的时候,就会弹出窗口,显示“yuanzm”,而后咱们按F12键,查看浏览器的调试窗口:

  browser-sessionStorage

  咱们可以发现,在浏览器的本地存储sessionStorage中已经有了key值为“myname”的项。这个时候,刷新页面,仍然会弹出“yuanzm”,由于若是不调用sessionStorage.removeItem()或者手动清除这个项的话,这个项将一直存在。而上面提到的“只要浏览器开着,页面会话周期就会一直持续。当页面从新载入(reload)或者被恢复(restores)时,页面会话也是一直存在的。每在新标签或者新窗口中打开一个新页面,都会初始化一个新的会话”的意思是说,若是咱们不从新设置myname的值,在新打开一个浏览器标签或者再次打开一个浏览器窗口的时候,这个值是不存在的,也就是null。为了验证这一点,很简单,咱们把上面两行代码的第一行注释掉,而后刷新页面,接着在新的浏览器标签中打开这个文件。这两个动做分别会产生什么效果呢?答案很简单,当再次刷新页面的时候,仍然会弹出“yuanzm”,由于这个数据已经保存在本地了,而修改代码以后在新的页面打开,获得的结果是null,由于当前页面会话中没有“myname”这个值。

  接下来咱们看一看localStorage,他是跨多个窗口,且持续范围可超过当前会话;意味着当浏览器关闭再从新打开,数据依然是可用的;拿上面的例子来讲,当修改代码以后,在新的标签打开页面,仍然会弹出“yuanzm”,咱们再次在浏览器中查看效果:

  brower-localStorage

  因为这两个对象的使用很简单,暂时就介绍到这里。下面还须要介绍一下的就是兼容性问题。缘由很简单,由于并非全部的浏览器都支持这两个对象。这里的兼容包括两种,第一种是在没有原生支持localStorage的浏览器中使用,第二种是兼容不一样浏览器对于这两种用法的差别。对于第一种,MDN给出了兼容代码:

if (!window.localStorage) {
  Object.defineProperty(window, "localStorage", new (function () {
    var aKeys = [], oStorage = {};
    Object.defineProperty(oStorage, "getItem", {
      value: function (sKey) { return sKey ? this[sKey] : null; },
      writable: false,
      configurable: false,
      enumerable: false
    });
    Object.defineProperty(oStorage, "key", {
      value: function (nKeyId) { return aKeys[nKeyId]; },
      writable: false,
      configurable: false,
      enumerable: false
    });
    Object.defineProperty(oStorage, "setItem", {
      value: function (sKey, sValue) {
        if(!sKey) { return; }
        document.cookie = escape(sKey) + "=" + escape(sValue) + "; path=/";
      },
      writable: false,
      configurable: false,
      enumerable: false
    });
    Object.defineProperty(oStorage, "length", {
      get: function () { return aKeys.length; },
      configurable: false,
      enumerable: false
    });
    Object.defineProperty(oStorage, "removeItem", {
      value: function (sKey) {
        if(!sKey) { return; }
        var sExpDate = new Date();
        sExpDate.setDate(sExpDate.getDate() - 1);
        document.cookie = escape(sKey) + "=; expires=" + sExpDate.toGMTString() + "; path=/";
      },
      writable: false,
      configurable: false,
      enumerable: false
    });
    this.get = function () {
      var iThisIndx;
      for (var sKey in oStorage) {
        iThisIndx = aKeys.indexOf(sKey);
        if (iThisIndx === -1) { oStorage.setItem(sKey, oStorage[sKey]); }
        else { aKeys.splice(iThisIndx, 1); }
        delete oStorage[sKey];
      }
      for (aKeys; aKeys.length > 0; aKeys.splice(0, 1)) { oStorage.removeItem(aKeys[0]); }
      for (var iCouple, iKey, iCouplId = 0, aCouples = document.cookie.split(/\s*;\s*/); iCouplId < aCouples.length; iCouplId++) {
        iCouple = aCouples[iCouplId].split(/\s*=\s*/);
        if (iCouple.length > 1) {
          oStorage[iKey = unescape(iCouple[0])] = unescape(iCouple[1]);
          aKeys.push(iKey);
        }
      }
      return oStorage;
    };
    this.configurable = false;
    this.enumerable = true;
  })());
}
View Code

  至于第二种,在github上面有不少优秀的代码,博主这里推荐其中一份:github localStorage

   最后,欢迎转载原文,可是但愿加上转载连接:http://www.cnblogs.com/yuanzm/p/4023295.html

相关文章
相关标签/搜索