Storage - Web 开发者指南 编辑

概述

DOM存储是一套在Web Applications 1.0 规范中首次引入的与存储相关的特性的总称, 现在已经分离出来,单独发展成为独立的W3C Web存储规范. DOM存储被设计为用来提供一个更大存储量,更安全,更便捷的存储方法,从而可以代替掉将一些不需要让服务器知道的信息存储到cookies里的这种传统方法.该特性在Firefox 2Safari 4中首次引入.

注意: DOM存储有别于mozStorage (Mozilla的XPCOM接口,用来访问SQLite) 也有别于Session store API (一个XPCOM 存储工具,主要为扩展程序使用).

描述

DOM存储的机制是通过存储字符串类型的键/值对,来提供一种安全的存取方式.这个附加功能的目标是提供一个全面的,可以用来创建交互式应用程序的方法(包括那些高级功能,例如可以离线工作一段时间).

基于Mozilla的浏览器, Internet Explorer 8+, Safari 4+ 以及 Chrome 都提供了自己的DOM存储规范的实现. (如果你想让自己的代码兼容多个浏览器,则你需要照顾一下老版本的IE浏览器,IE下有一个类似的特性,在IE8之前版本也可以使用,叫做"userData behavior",它允许你在多重浏览器会话中永久地保存数据.)

DOM存储很有用,因为在浏览器端没有好的方法来持久保存大量数据。浏览器cookie的能力有限,而且不支持组织持久数据,其他方法(如flash本地存储)需要外部插件支持。

Aaron Boodman编写的halfnote(笔记类应用程序)是第一批使用新的DOM存储功能(不包括internet explorer的userData behavior)开发的公开应用程序之一。在这个应用里,Aaron同时将笔记保存到服务器(当网络可用时)和本地,这允许使用者即使在不稳定的网络环境下也能安全的记录备注事项。

虽然halfnote的理念和实现比较简单,但是halfnote的创新展示了一种在线上和线下都可用的新型web应用的可能性。

参考

以下所提到的对象都是全局对象,作为 window 对象 的属性存在。这意味着可以以 sessionStorage 或者 window.sessionStorage 的形式访问这些对象。(这点很重要,因为可以使用iframe来存储、访问除了直接包含在页面的数据之外的附加数据。)

Storage

它是所有Storage实例(sessionStorageglobalStorage[location.hostname])的构造函数,设置Storage.prototype.removeKey = function(key) { this.removeItem(this.key(key)) },可通过localStorage.removeKeysessionStorage.removeKey访问到。

globalStorage对象不是Storage的实例,而是StorageObsolete的一个实例。

Storage被定义在WhatWG Storage Interface 中,如下:

interface Storage {
  readonly attribute unsigned long length;
  [IndexGetter] DOMString key(in unsigned long index);
  [NameGetter] DOMString getItem(in DOMString key);
  [NameSetter] void setItem(in DOMString key, in DOMString data);
  [NameDeleter] void removeItem(in DOMString key);
  void clear();
};
注意:虽然可以直接通过标准的 JavaScript 属性访问方法来设置和读取值,但是推荐的做法是使用 getItem 和 setItem 方法。 注意:需要时刻注意的一点是,所有数据在被保存到下面将要介绍的任何一个存储器之前,都将通过它的 .toString 方法被转换成字符串。所以一个普通对象将会被存储为 "[object Object]",而不是对象本身或者它的 JSON 形式。使用浏览器自身提供的 JSON 解析和序列化方法来存取对象是比较好的,也是比较常见的方法。

sessionStorage

sessionStorage 是个全局对象,它维护着在页面会话(page session)期间有效的存储空间。只要浏览器开着,页面会话周期就会一直持续。当页面重新载入(reload)或者被恢复(restores)时,页面会话也是一直存在的。每在新标签或者新窗口中打开一个新页面,都会初始化一个新的会话。 

// 保存数据到当前会话的存储空间
sessionStorage.setItem("username", "John");

// 访问数据
alert( "username = " + sessionStorage.getItem("username"));

当浏览器被意外刷新的时候,一些临时数据应当被保存和恢复。sessionStorage 对象在处理这种情况的时候是最有用的。

Firefox 3.5 note

在Firefox 3.5之前的版本中,如果浏览器意外崩溃,则在重启后,sessionStorage中保存的数据不会被恢复.之后的版本中,会恢复上次崩溃前的sessionStorage数据.

例子:

自动保存一个文本域中的内容,如果浏览器被意外刷新,则恢复该文本域中的内容,所以不会丢失任何输入的数据。

 // 获取到我们要循环保存的文本域
 var field = document.getElementById("field");

 // 查看是否有一个自动保存的值
 // (只在浏览器被意外刷新时)
 if ( sessionStorage.getItem("autosave")) {
    // 恢复文本域中的内容
    field.value = sessionStorage.getItem("autosave");
 }

 // 每隔一秒检查文本域中的内容
 setInterval(function(){
    // 并将文本域的值保存到session storage对象中
    sessionStorage.setItem("autosave", field.value);
 }, 1000);

更多信息:

localStorage

localStorage is the same as sessionStorage with same same-origin rules applied but it is persistent. localStorage was introduced in Firefox 3.5.

注意:当浏览器进入私人模式(private browsing mode,Google Chrome 上对应的应该是叫隐身模式)的时候,会创建一个新的、临时的、空的数据库,用以存储本地数据(local storage data)。当浏览器关闭时,里面的所有数据都将被丢弃。

兼容性

这些Storage 对象最近刚被加入标准当中,所以并不是所有的浏览器都支持。如果你想在没有原生支持 localStorage 对象的浏览器中使用它,可以在你编写的 JavaScript 代码的首部插入下面两段代码中的任意一段。

This algorithm is an exact imitation of the localStorage object, but making use of cookies.

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;
  })());
}
Note: The maximum size of data that can be saved is severely restricted by the use of cookies. With this algorithm, use the functions localStorage.setItem() and localStorage.removeItem() to add, change or remove a key. The use of methods localStorage.yourKey = yourValue; and delete localStorage.yourKey; to set or delete a key is not a secure way with this code. You can also change its name and use it only to manage a document's cookies regardless of the localStorage object.

Here is another, less exact, imitation of the localStorage object. It is simpler than the previous one, but it is compatible with old browsers, like Internet Explorer < 8. It also makes use of cookies.

if (!window.localStorage) {
  window.localStorage = {
    getItem: function (sKey) {
      if (!sKey || !this.hasOwnProperty(sKey)) { return null; }
      return unescape(document.cookie.replace(new RegExp("(?:^|.*;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"), "$1"));
    },
    key: function (nKeyId) { return unescape(document.cookie.replace(/\s*\=(?:.(?!;))*$/, "").split(/\s*\=(?:[^;](?!;))*[^;]?;\s*/)[nKeyId]); },
    setItem: function (sKey, sValue) {
      if(!sKey) { return; }
      document.cookie = escape(sKey) + "=" + escape(sValue) + "; path=/";
      this.length = document.cookie.match(/\=/g).length;
    },
    length: 0,
    removeItem: function (sKey) {
      if (!sKey || !this.hasOwnProperty(sKey)) { return; }
      var sExpDate = new Date();
      sExpDate.setDate(sExpDate.getDate() - 1);
      document.cookie = escape(sKey) + "=; expires=" + sExpDate.toGMTString() + "; path=/";
      this.length--;
    },
    hasOwnProperty: function (sKey) { return (new RegExp("(?:^|;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie); }
  };
  window.localStorage.length = (document.cookie.match(/\=/g) || window.localStorage).length;
}
Note: The maximum size of data that can be saved is severely restricted by the use of cookies. With this algorithm, use the functions localStorage.getItem(), localStorage.setItem() and localStorage.removeItem() to get, add, change or remove a key. The use of method localStorage.yourKey in order to get, set or delete a key is not permitted with this code. You can also change its name and use it only to manage a document's cookies regardless of the localStorage object.
与 globalStorage 的关系的兼容性

localStorage is also the same as globalStorage[location.hostname], with the exception of being scoped to an HTML5 origin (scheme + hostname + non-standard port) and localStorage being an instance of Storage as opposed to globalStorage[location.hostname] being an instance of StorageObsolete which is covered below. 例如,在 http://example.com 中不能访问 https://example.com 中的 localStorage 对象,但是它们都可以访问同一个 globalStorage。 localStorage 是个标准接口,但 globalStorage 是非标准的。所以你的代码最好不要依赖这些关系。

Please note that setting a property on globalStorage[location.hostname] does not set it on localStorage and extending Storage.prototype does not affect globalStorage items, only extending StorageObsolete.prototype does.

globalStorage

非标准
该特性是非标准的,请尽量不要在生产环境中使用它!

已废弃 Gecko 13.0 (Firefox 13.0 / Thunderbird 13.0 / SeaMonkey 2.10)
This feature is obsolete. Although it may still work in some browsers, its use is discouraged since it could be removed at any time. Try to avoid using it.

globalStorageis obsolete since Gecko 1.9.1 (Firefox 3.5) and unsupported since Gecko 13 (Firefox 13). Just uselocalStorageinstead. This proposed addition to HTML 5 has been removed from the HTML 5 specification in favor of <code>localStorage</code>, which is implemented in Firefox 3.5. This is a global object (globalStorage) that maintains multiple private storage areas that can be used to hold data over a long period of time (e.g. over multiple pages and browser sessions). Note: globalStorage is not a Storage instance, but a StorageList instance containing StorageObsolete instances.
// Save data that only scripts on the mozilla.org domain can access
globalStorage['mozilla.org'].setItem("snippet", "<b>Hello</b>, how are you?");

Specifically, the globalStorage object provides access to a number of different storage objects into which data can be stored. For example, if we were to build a web page that used globalStorage on this domain (developer.mozilla.org) we'd have the following storage object available to us:

  • globalStorage['developer.mozilla.org'] - All web pages within the developer.mozilla.org sub-domain can both read and write data to this storage object.

例子:

All of these examples require that you have a script inserted (with each of the following code) in every page that you want to see the result on.

Remember a user's username for the particular sub-domain that is being visited:

 globalStorage['developer.mozilla.org'].setItem("username", "John");

Keep track of the number of times that a user visits all pages of your domain:

 // parseInt must be used since all data is stored as a string
 globalStorage['mozilla.org'].setItem("visits", parseInt(globalStorage['mozilla.org'].getItem("visits") || 0 ) + 1);

存储位置以及清除数据

In Firefox the DOM storage data is stored in the webappsstore.sqlite file in the profile folder (there's also chromeappsstore.sqlite file used to store browser's own data, notably for the start page - about:home, but potentially for other internal pages with "about:" URLs).

  • DOM Storage can be cleared via "Tools -> Clear Recent History -> Cookies" when Time range is "Everything" (via nsICookieManager::removeAll)
    • But not when another time range is specified: (bug 527667)
    • Does not show up in Tools -> Options -> Privacy -> Remove individual cookies (bug 506692)
  • DOM Storage is not cleared via Tools -> Options -> Advanced -> Network -> Offline data -> Clear Now.
  • Doesn't show up in the "Tools -> Options -> Advanced -> Network -> Offline data" list, unless the site also uses the offline cache. If the site does appear in that list, its DOM storage data is removed along with the offline cache when clicking the Remove button.

See also clearing offline resources cache.

更多信息

例子

  • JavaScript Web Storage Tutorial: Creating an Address Book Application - hands-on tutorial describing how to use the Web Storage API by creating a simple address book application
  • offline web applications at hacks.mozilla.org - showcases an offline app demo and explains how it works.
  • Noteboard - Note writing application that stores all data locally.
  • jData - A shared localStorage object interface that can be accessed by any website on the internet and works on Firefox 3+, Webkit 3.1.2+ nightlies, and IE8. Think of it as pseudo-globalStorage[""] but write access needs user confirmation.
  • HTML 5 localStorage example. Very simple and easy to understand example of localStorage. Saves and retrieves texts and shows a list of saved items. Tested in Firefox 3 or higher.
  • HTML5 Session Storage. A very simple example of session storage. Also includes a example on local storage. Tested in Firefox 3.6 or higher.
  • Basic DOMStorage Examples - Broken in Firefox 3 and up due to use of globalStorage on one domain level up from the current domain which is not allowed in Firefox 3.
  • halfnote - (displaying broken in Firefox 3) Note writing application that uses DOM Storage.

浏览器兼容性

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!
FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafari (WebKit)
localStorage43.5810.504
sessionStorage52810.504
globalStorage未实现2-13未实现未实现未实现
FeatureAndroidFirefox Mobile (Gecko)IE PhoneOpera MobileSafari Mobile
Basic support?????

All browsers have varying capacity levels for both local- and sessionStorage. Here is a detailed rundown of all the storage capacities for various browsers.

 

相关链接

HTML5 Documentation
HTML
JavaScript
CSS

---------------------------------

 

摘要

DOM Storage,就是在Web Applications 1.0 specification中介绍的那些存储相关特性集合的名称。相比较在cookies中存储信息来说,DOM Stroage更大、更安全、更易于使用的。目前支持的浏览器包括Mozilla Firefox 2+, Google Chrome, Apple Safari, Opera和Microsoft IE9+,在移动设备上也包括iPhone & iPad Safari。

Note: DOM Storage 与 mozStorage (Mozilla对于SQLite的XPCOM接口)和Session store API(扩展使用的一个XPCOM存储).不同

描述

DOM Storage机制是一种通过字符串形式的名/值对来安全地存储和使用的方法。这个附加功能的目标是提供一个更全面的、可以创建交互式应用程序的方法(包括那些高级功能,例如可以离线工作一段时间)。

目前,只有基于Mozilla的浏览器提供了DOM Storage的实现。不过,Internet Explorer也有一个类似的特性,叫做"userData behavior",他允许你在多重浏览器会话中永久地保存数据。

DOM Storage 是很有用的,因为在任何一段时期都没有一个很好的、只通过浏览器来永久存储合理大小的数据的方法。浏览器cookies 限制了存储容量,而且并没有为组织永久性的数据提供支持,并且其他的方法还需要外部插件来实现(例如Flash Local Storage)。

第一个使用了新的DOM Storage功能(除了Internet Explorer 的 userData Behavior之外)的公共应用程序是由 Aaron Boodman 写的 halfnote(一个便签应用程序) 。在他的程序中,Aaron同时把便签内容保存到服务器上(当Internet连接可用时)和一个本地数据存储中。这就允许用户即便是在不定式发生internet连接中断时,也可以安全的写一些有备份的便签。

不过,在halfnote中表现出来的概念和实现,都还是相对简单的。它的诞生揭示了一种新的、可以在线或离线使用的网络应用程序。

参考

下面的内容都是作为每个window 对象的属性存在的全局对象。这也就是说,可以通过sessionStorage 或者 window.sessionStorage 来访问它们。(这很重要,因为随后你可以使用iframe来存储、访问、添加那些并不是立刻就包含在你页面中的数据。)

sessionStorage

这是一个全局对象(sessionStorage),它含有一个在页面会话有效期内可用的存储区域。只要页面没有关闭,一个页面会话就始终保持着,并且当页面被重新载入或恢复时“复活”。打开一个新的标签页或新窗口都会初始化新的会话。

// 将数据存入当前会话的一个存储中
sessionStorage.username = "John";

// 访问某些已存储的数据
alert( "username = " + sessionStorage.username );

sessionStorage 对象是最有用的,它持有那些应该保存的临时数据,而且一旦浏览器突然被刷新时,要恢复的那些数据,

Note: sessionStorage 还应该有在浏览器崩溃后存储和恢复数据的功能,不过由于bug 339445的原因,这个功能到现在还没有在Firefox中实现。这个功能实现之后,sessionStorage的防御功能就十分有用了。

举例:

自动保存文本字段的内容,如果浏览器突然被刷新,就恢复字段内容,这样就不会丢失任何输入了。

 // 获得我们要跟踪的那个文本字段
 var field = document.getElementById("field");

 // 看看我们是否有一个autosave的值
 // (这将只会在页面被突然刷新时发生)
 if ( sessionStorage.autosave ) {
     // 恢复文本字段中的内容
     field.value = sessionStorage.autosave;
 }

 // 每秒钟检查一次文本字段的内容
 setInterval(function(){
     // 并把结果保存到会话存储对象中
     sessionStorage.autosave = field.value;
 }, 1000);

更多信息:

globalStorage

这是一个全局对象(globalStorage),它维护着各种公共的或者私有的,可以用来长时期保存数据的存储空间(例如,在多重的页面和浏览器会话之间)。

// 可以这样访问那些仅对mozilla.org域上的脚本保存的数据
globalStorage['mozilla.org'].snippet = "<b>Hello</b>, how are you?";

// 可以这样访问为任何网页任何域存储的数据
globalStorage[''].favBrowser = "Firefox";

特别地,globalStorage对象,提供了访问一些不同的可以保存数据的存储对象的方法。例如,如果我们要建立一个可以在域(developer.mozilla.org)下面可以使用globalStorage的网页,我们有下面这些存储对象可以使用:

  • globalStorage['developer.mozilla.org'] - 在developer.mozilla.org下面所有的子域都可以通过这个存储对象来进行读和写。
  • globalStorage['mozilla.org'] - 在mozilla.org域名下面的所有网页都可以通过这个存储对象来进行读和写。
  • globalStorage['org'] - 在.org域名下面的所有网页都可以通过这个存储对象来进行读和写。
  • globalStorage[] - 在任何域名下的任何网页都可以通过这个存储对象来进行读和写。
注意: firefox目前还没有实现globalStorage[tld]globalStorage[] (会抛出一个安全错误),这是由于对于这些名字空间可以进行随意读写的话是有安全漏洞的 更多信息

示例:

下面这些示例,需要你在所有想看到效果的页面中都插入脚本(包括如下所有的代码)。

记录某个指定子域名下面正在访问的用户的username:

 globalStorage['developer.mozilla.org'].username = "John";

跟踪一个用户在你的域名下所访问的所有页面的次数:

 // 由于所有数据都是被当作一个字符串来保存的,所以这里必须使用parseInt
 globalStorage['mozilla.org'].visits =
     parseInt( globalStorage['mozilla.org'].visits || 0 ) + 1;

记录所有你访问的网站:

 globalStorage[''].sites += "," + location.hostname;

更多信息:

More information

Examples

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

词条统计

浏览:99 次

字数:39334

最后编辑:7 年前

编辑次数:0 次

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文