您的位置:首页 > Web前端 > HTML5

HTML5 Web存储(Web Storage)(3)

2015-12-20 16:27 393 查看
本地持久化存储一直是本地客户端程序优于 web 程序的一个方面。对于本地应用程序,操作系统会一共一个抽象层,

用于存储和获取特定于应用程序的数据,例如用户设置或者运行时状态。这些值可以被存储于注 册表、INI 文件,或者其他什么地方,

这取决于操作系统的实现。如果你的本地应用程序需要不简单是键值对形式的本地存储,你也可以使用嵌入式数据库、发明你自己的文件 格式,或者其他很多种解决方案。

然而,web 应用程序就没这些优点了。于是在 web 早期我们就发明了 cookie,目的是在本地持久存储少量数据。但是,cookie 有三个致命缺点:

cookie 会包含进每一个 HTTP 请求,因此会减慢 web 应用程序,产生不必要的重复数据;

cookie 会包含进每一个 HTTP 请求,因此网络上发送的数据就不能加密(除非你的整个应用都是用的 SSL)

cookie 限制数据大小为 4 KB——这已经足以降低你的应用程序的速度,但是 4 KB 的大小有时候确实会捉襟见肘。

我们真正想要的是:

更大的存储空间

在客户端上的

不受页面刷新的影响

不需要提交到服务器

在 HTML5 之前,我们没有任何办法能够同时满足以上要求。

HTML5 之前的解决方案

一开始,我们的浏览器只有 Internet Explorer。或者说,那是 Microsoft 所期望的世界。到后来,在第一次浏览器大战期间,

Microsoft 发明了一大堆东西,全部包含进了 Internet Explorer,而这个浏览器赢得了第一次浏览器大战。这其中之一就是 DHTML

行为(DHTML Behaviors),其中有一个行为叫做“用户数据 userData”。 userData 允许每一个域名的页面保存64KB数据,包括有层次结构的基于 XML 的结构。(受信域名,例如 intranet 站点,可以存储10倍于这个数字,也就是640KB。这几乎对任何人都已经足够了。)IE 不会有任何授权对话框,也不能增加额外的存储空间。

2002年,Adobe 在 Flash 6 引入了一项新的特性,却有一个明显会误导的名字:Flash cookie。在 Flash 环境下,这个特性被称为 Local Shared Object。

简单来说,它允许每个域名的 Flash 对象存储100KB数据。Brad Neuberg 开发了一个 Flash-JavaScript 桥的早期原型,称为 AMASS(AJAX Massive Storage System),但它受限于 Flash 的设计怪癖。直到2006年,Flash 8 提供了 ExternalInterface,这么一来就可以由 JavaScript 直接访问 LSO,因此访问速度提升了一个数量级,

变得更简单更快速。Brad 重写了 AMASS,并将其集成在 Dojo Toolkit 的 dojox.storage 中。Flash 给每个域名100KB的自由空间。如果超出,则允许按照数量级增加(1Mb、10Mb等等)。 2007年,Google 提供了 Gears,一个开源的浏览器插件,旨在为浏览器提供额外的功能。(我们曾经在为 IE 提供地理位置API的时候介绍过 Gears。)Gears 提供了一组基于 SQLite 的嵌入式数据库的 API。只要用户一次授权,Gears 能够按照域名在 SQL 数据库表中存储无限大小的数据。 与此同时,Brad Neuberg 和其他人继续 dojox.storage 的开发,以提供一种对这类插件和 API 的统一的接口。2009年,dojox.storage 能够自动检测(在其上层提供一种统一的接口)

Adobe Flash、Gears、Adobe AIR 和 HTML5 存储的早期原型(仅有 Firefox 的一个较老版本实现)。 正如你所看到的这些解决方案,它们都有或多或少的问题:

不是特定于某一浏览器,就是需要安装第三方插件。我们还需要对不同之处做一种“屏蔽”(正如 dojox.storage 所做的那样),它们有着不同的接口、不同的存储限制、

不同的用户体验。这就是 HTML5 所要解决的问题:提供一种标准的 API,由多种浏览器提供原生支持,不需要安装第三方插件。

HTML5 存储简介

我所说的“HTML5 存储(HTML5 Storage)”,也就是标准上说的 Web Storage,这曾经是 HTML5 标准的一部分,后来由于某些不和谐的政治因素从 HTML5 分离,

成为一个独立的标准。有些浏览器厂商也称为“本地存储 Local Storage” 或者 “DOM 存储 DOM Storage”。由于一些相关的问题、相似的名字、标准的合并问题等等,

这个名字变得相当复杂,我们会再和后面的内容中仔细讲解。 那么,什么是 HTML5 Storage 呢?简单来说,就是一种让 web 页面能够以键值对的形式,

在客户端web浏览器中将数据存储在本地的方法。就像 cookie 一样,这种数据在你离开 web 站点、关闭标签页、退出浏览器等等的时候依然保存。

不同于 cookie 的地方是,这个数据不会被发送到远程 web 服务器(除非你自己手动发送)。另外,不同于我们前面所说的那些解决方案,

这种机制是 web 浏览器原生提供的,所以不需要第三方插件的支持。 那么,什么浏览器才支持呢?目前,几乎所有主流浏览器的最新版本都支持 HTML5 Storage 了,

甚至包括 Internet Explorer!

IEFirefoxSafariChromeOperaiPhoneAndroid
8.0+3.5+4.0+4.0+10.5+2.0+2.0+
我们可以使用 JavaScript 来访问 HTML5 Storage,通过全局的 window 对象的 localStorage 对象。在我们使用之前,我们需要首先检测是否可用:

function supports_html5_storage() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
}


当然,我们也可以使用 Modernizr 检测:

if (Modernizr.localstorage) {
// window.localStorage is available!
} else {
// no native support for HTML5 storage :(
// maybe try dojox.storage or a third-party solution
}


使用 HTML5 Storage

HTML5 Storage 基于键值对存储。你要存储的数据需要有一个名字作为键,然后你就可以使用这个键读取这个数据。这个键是一个字符串;

数据则可以是 JavaScript 支持的任何数据类型,包括字符串、布尔值、整数和浮点数。但是,我们通常将数据作为字符串进行存储。

如果你存储读取非字符串数据,你就得使用类似 parseInt() 或者 parseFloat() 这样的函数,将读取的数字转换成所需要的 JavaScript 数据类型。

interface Storage {
getter any getItem(in DOMString key);
setter creator void setItem(in DOMString key, in any data);
};


调用 setItem() 时需要有一个键作为参数。如果这个键已经存在,则原有的值将被覆盖。getItem() 也要有一个键作为参数,如果该键不存在,

则会直接返回 null,不会引发异常。 正如其他的 JavaScript 对象,你可以将 localStorage 对象作为一个关联数组。

除了使用 getItem() 和 setItem() 函数,也可以直接使用方括号语法。例如:

var foo = localStorage.getItem("bar");
// ...
localStorage.setItem("bar", foo);


也可以写成:

var foo = localStorage["bar"];
// ...
localStorage["bar"] = foo;


当然也有函数,用于删除已有的值,清空整个存储区域(也就是一次性将所有键和值全部删除)等。

interface Storage {
deleter void removeItem(in DOMString key);
void clear();
};


调用 removeItem() 时传入一个不存在的键不会做任何动作。 最后,有一个属性可以获得存储区域中值的总数,

借助另外一个函数则可以使用索引进行遍历(获取每个键的名字)。

interface Storage {
readonly attribute unsigned long length;
getter DOMString key(in unsigned long index);
};


调用 key() 的索引如果不在 0 – (length-1) 之间,函数将返回 null。

HTML5 Storage 变化追踪

如果你需要以编程方式跟踪存储区域的改变,你需要使用 storage 事件。storage 事件在 window 对象调用 setItem()、removeItem() 或者 clear(),并且的确有东西改变的时候会被派发。例如,如果你设置一个已存在的值,或者在一个空的存储区域调用 clear() 函数,因为没有任何动作,所以就不会触发 storage 事件。 只要支持 localStorage 对象的地方都会支持storage 事件,包括 IE8。IE 8 不支持 W3C 的标准的 addEventListener(事实上这一函数在 IE 9 才被加入)。因此,为了监听 storage 事件,你需要检测浏览器支持哪种事件机制(如果你了解这个内容,就可以跳过这部分了。处理 storage 事件同其他时间一样。如果你使用 jQuery 或者其他 JavaScript 库的事件处理函数,那么你也可以这么处理 storage 事件。)

if (window.addEventListener) {
window.addEventListener("storage", handle_storage, false);
} else {
window.attachEvent("onstorage", handle_storage);
};


handle_storage 回调函数接受一个 StorageEvent 参数。在 Internet Explorer 中,event 对象则存在 window.event 里面。

function handle_storage(e) {
if (!e) { e = window.event; }
}


此时,变量 e 就是一个 StorageEvent 对象。这个对象有很多有用的属性。

StorageEvent 对象
属性类型说明
keystring增加、删除或者修改的那个键
oldValueany改写之前的旧值,如果是新增的元素,则是 null
newValueany改写之后的新值,如果是删除的元素,则是 null
url*string触发这个改变事件的页面 URL
*注意:url 属性最早叫做 uri。有些浏览器在标准修改之前就已经发布了。为了最大兼容,你应该检测是否存在这个 url 属性,如果没有,则要检测 uri 属性。
storage 事件不能取消。在 handle_storage 回调函数中,没有方法能够终止事件。浏览器只会简单地告诉你,“就是发生了!你现在什么也干不了了!我只是告诉你,它就是发生了。” via:DevBean
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: