低代码到底是不是行业毒瘤?一线大厂怎么做的?戳此了解>>> 了解详情
写点什么

HTML5 存储 API 介绍

2011 年 9 月 14 日

目录

HTML5 的最有趣的功能之一是本地存储数据并且允许应用程序离线运行的功能。 共有三种不同的处理这些功能的 API,如何选中其中之一取决于你希望对你将要本地存储的数据进行怎样处理:

  • Web 存储:适用于具有 key/value 对的基本本地存储
  • 离线存储:利用一个 manifest 文件来高速缓存所有文件以便离线使用
  • Web 数据库:适用于关系型数据库存储

要求

预备知识:

应该熟悉 JavaScript 的在线和离线数据存储技术。

需要下列产品:

Dreamweaver

Web 存储 API

在用户的机器上进行本地存储的最基本的实现方法是利用 web 存储 API。 该 API 使用 key/value 对来支持开发人员存储能够被 web 应用程序访问的基本信息和变量。 该功能的一个理想用例是用于存储那些在用户已经浏览完并且离开应用程序或已经关闭 web 浏览器之后需要永久保留的简单数据。 例如,保存游戏状态、保存导航位置或存储你希望在整个 web 应用程序中使用但你不希望使用 cookie 的一些特定信息(例如用户名称或姓名)。 类似的 API 还可以用于为个体会话存储数据。 这些数据将在用户浏览完离开应用程序或关闭浏览器之后自动清除。

当使用 web 存储 API 时,你需要记住下列事项:

  • 该存储操作只能适用于相关的域(domain-wide),因此当使用 web 存储功能保存数据时,只有在该域上的其它网站才能访问这些数据。
  • 存储数据的大小限制是大约 5M 字节。 5M 字节的限制是由 W3C 建议的 * ,但该规范提供了实现细节的一些保留空间,因此,实际的字节大小取决于每个浏览器厂商。

核查浏览器支持功能

在使用 web 存储 API 之前需要做的第一件事情是核查用户的浏览器是否支持这一 API:

复制代码
function checkLocalStorageSupport() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
}

你也许在上面的代码片段中明显地看出,web 存储使用一个名称为 localStorage 的对象,它是一个 windowclass 对象。 上面的代码片段能够核查 localStorage 实际上是否是一个基于 window 的对象,以及它能否返回 true,以便应用程序能够充分利用本地存储 API。

添加和返回数据

从 localStorage 对象中添加和返回数据与调用由本地存储规范实现的 getter 和 setter 方法一样简单。 使用 localStorage 可以存储任何类型的数据,但所有的数据必须以字符串的格式存储于相应的存储区域。 这意味着在将数据发送到 localStorage 之前或在使用它们之后有必要对它们进行解析。 例如,为了存储一个 JavaScript 对象,必须使用 JSON 并且在检索数据之前调用 stringify() 而在检索数据之后调用 parse()。 在从 localStorage 对象中检索到数值变量之后,对它们进行解析也是如此。

在本范例中,已经建立一个单一的表单输入,这样,当用户点击 Submit 时,相应的数据将存储到本地高速缓存区域。 当加载页面时,如果数据已经存储,则页面将通过一个欢迎窗口显示已存储的信息。 下面是当用户点击 Submit 时调用的函数:

复制代码
function onClick()
{
if(checkLocalStorageSupport)
{
window.localStorage.setItem("name",document.getElementById("name").value);
}
}

该函数使用 localStorage 对象中的 setItem 方法,然后使用相应表单中的值来填充存储高速缓存区。 当加载页面时,应用程序利用一个 onLoad 函数来核查相应的数据是否已经位于本地高速缓存区中并且将添加一个欢迎窗口。

复制代码
function onLoad()
{
if(checkLocalStorageSupport)
{
var name = window.localStorage.getItem("name");
if(name != null)
{
window.document.getElementById("divName").innerHTML = "Welcome back " + name;
}
}
}

清除数据

尽管用户能够使用浏览器在任何时间删除 localStorage 数据,但为他们提供从应用程序自身删除数据的选项也是合理的。localStorage 提供一个正好能够实现这一目的 clear() 方法。 当用户在你的应用程序中点击一个复位按钮时,将触发下面代码。 如果你希望从存储区中移除一个特定条目,则你可以使用 removeItem() 方法从本地存储区中删除一个单一 key。

复制代码
function onReset()
{
if(checkLocalStorageSupport())
{
window.localStorage.clear();
}
}

处理变更

Web 存储 API 还包含一种侦听和响应任何本地存储变更的方法。 通过添加一个事件侦听程序以及侦听一个 storage 事件,应用程序能够对 localStorage 变更进行响应。 事件中的数据包含已更改的 key 的名称、新值、老值(如果有的话)以及调用该 API 的页面的 URL。 可以利用下面的方式实现 localStorage API 的规范要求,即发起事件的会话将不能看到该事件的触发。 这是因为规范要求该事件只能针对其它、而不是更改存储的标签或会话进行触发。

为了侦听存储事件,首先需要做的事情是添加事件侦听程序:

复制代码
window.addEventListener("storage",onStorageChange);

然后建立 onStorageChange 事件来处理存储事件。

复制代码
function onStorageChange(e) {
if(e.key == "name")
{
alert(e.newValue + ' just added their name to local storage');
}
}

另外,有一个创建数据的类似 API,它只对个体会话持续有效。 通过使用 sessionStorage 对象,而不是 localStorage 对象,当用户离开页面时,任何保存的数据将被自动清除。 事实上,API 具有完全相同的方法,因此你可以仔细检查并且利用 sessionStorage 替换 localStorage,然后本地数据将被保存直到用户关闭他们的浏览器或其中包含应用程序的标签。

离线存储

有时在用户的机器中仅仅存储一些数据是不能满足要求的。 在许多情形下,整个应用程序必须离线运行,而不仅仅存储一些数据。 对于这种使用情形,HTML5 包含了在用户机器上高速缓存文件和资源的功能,以便浏览器在没有因特网连接的情形下访问它们。 这意味着构成web 应用程序的图像、JavaScript 文件、 HTML 文件、 CSS 文件等大量数据能够本地存储,甚至在没有因特网连接的情形下能够对它们进行访问。 这一功能的关键是建立一个高速缓存的Manifest 文件。

使用 manifest 文件

Manifest 文件是页面的根 HTML 标签的新 manifest 属性的一个组成部分。 它是一个位于 web 服务器上的文件,它能够列出浏览器应该下载和保存以便以后使用的所有文件。 它具有一个 .manifest 扩展名并且其唯一主要的 gotcha 是相应的 web 服务器必须支持 .manifest mime 类型,因此,应该确保驻留应用程序的该 web 服务器能够正确提供.manifest 文件。 Manifest 文件具有一个基本架构。 每个 manifest 文件以 CACHE MANIFEST 开头,并且从这里开始,列出所有浏览器需要高速缓存的、用于离线访问的文件。 下面是一个简单范例,它能够存储一些 JavaScript、一个 CSS 文件、一些图像和 相应的 HTML 页面:

复制代码
CACHE MANIFEST
style.css
offlinescript.js
images/dreamweaver_logo.png
images/edge_logo.png

相应的路径均与用户正在访问的 HTML 页面相关。 当创建高速缓存 manifest 文件时,你必须了解一些其它选项。 其中一个选项是绝不能高速缓存的文件的情形。 也许只有能够在线获得的动态脚本或某些内容才是有意义的。 高速缓存 manifest 文件能够划分为告知浏览器如何对某些内容进行响应的区段(section)。 通过创建一个 NETWORK 和列出那些绝不能高速缓存的文件,浏览器一定能够忽略这些文件并且让人们决不能离线获得它们。

另一个情形是当用户试图访问一个没有高速缓存的页面或某些应该高速缓存但却没有正确保存的内容时的情形。 高速缓存 manifest API 能够提供一个 FALLBACK 区段(section),它指向一个在上述用例中加载的页面。 因此,当用户试图访问没有保存的某些内容时,他们将看到一条关于离线提示的消息。 下面是一个理论上的包含这些区段(section)的高速缓存 Manifest 文件的大概架构:

复制代码
CACHE MANIFEST
NETWORK:
my_dynamic_script.cgi
FALLBACK:
my_offline_message.html
CACHE:
style.css
offlinescript.js
images/dreamweaver_logo.png
images/edge_logo.png

在本例中,我提供了一个带有一个外部 JavaScript 页面和外部 CSS 页面的 HTML 页面。 该 HTML 页面能够显示一些描述一个 Adobe 徽标的文本,并且当你点击相应的图像时,JavaScript 将会为另一个徽标换出相应的图像和文本。 下面是相应的 HTML 代码,紧跟其后的是 JavaScript 函数:

复制代码
<html xmlns="http://www.w3.org/1999/xhtml" manifest="cache.manifest">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Adobe Logos</title>
<script src="offlinescript.js"></script>
<link href="style.css" rel="stylesheet" />
</head>
<body>
<div id="textContent">This is the Edge logo:</div><br />
<img id="logo" name="logo" src="images/edge_logo.png" onclick="onLogoClick();" />
<p class="small">Click on the logo to swap it out.</p>
</body>
</html>
// JavaScript Document
function onLogoClick(e)
{
var currentContent =
window.document.getElementById("textContent").innerHTML;
if(currentContent == "This is the Edge logo:")
{
window.document.getElementById("textContent").innerHTML =
"This is the Dreamweaver logo:";
window.document.logo.src =
"images/dreamweaver_logo.png";
} else {
window.document.getElementById("textContent").innerHTML =
"This is the Edge logo:";
window.document.logo.src = "images/edge_logo.png";
}
}

所有这些代码的关键部分是带有 manifest 属性的 HTML 标签。 它是指向我在上面引用的我的 cache.manifest 文件。 该 manifest 文件能够指示浏览器下载列表中给出的所有文件。 不管用户在浏览这些文件时是否下载它们,相应的浏览器将自动下载 manifest 文件中包含的所有文件。 这意味着两个图像都将被保存以便离线访问,即使第二个图像直到我与相应内容互动时才加载到页面。 因此,只需加载该页面一次,我即可以在离线情形下完全与它进行互动,并且两个图像均会旋转。

了解事件

需要略微提到的、但却是非常重要的离线访问的最后部分是发生在高速缓存过程中的事件。 当浏览器遇到 manifest 属性,它将在 window.applicationCache 对象中触发一系列事件。 第一个发生的事件是触发一个 checking 事件。 该事件可以确定需要利用这一特别的高速缓存文件进行哪些操作。 Google Chrome 开发人员工具可以在高速缓存区保存数据时能够全面地核查发生的事件(参见图 1)。

在高速缓存区保存数据时发生的事件

图 1. 在高速缓存区保存数据时发生的事件

如果这是用户第一次访问该网站,则将触发一个下载事件并且相应的 web 浏览器将仔细查看并且下载 manifest 文件中包含的所有资源。 它能够读取相应的 manifest 文件,确定它需要下载多少文件,然后以 progress 事件的形式为每个文件回送状态更新信息。 Progress 事件包含一个已加载的变量和一个总变量,这样开发人员能够确定高速缓存区已经存储的多少内容。

复制代码
function onProgress(e)
{
var content = window.document.getElementById("loadedInfo").innerHTML;
window.document.getElementById("loadedInfo").innerHTML = content + '
Loaded file ' + e.loaded + ' of ' + e.total;
}

当完成所有文件的保存操作时,浏览器将触发一个 cached 事件通知开发人员所有用于离线使用的文件已经成功保存。

在后面用户访问页面的任何时刻,浏览器将核查看一看在 manifest 文件中是否有内容发生改变。 如果没有,它将触发一个 noupdate 事件,然后继续运行。 如果其中有内容发生改变,则它将经历与上面完全相同的过程;它将触发一个包含一系列 progress 事件的 downloading 事件,直到相应的文件全部更新完毕。 当该事件发生时,而不是触发一个 cached 事件,浏览器将触发一个 updateready 事件表示所有的文件已经更新并且可以离线使用。

最后一个令人发愁的事件是 error 事件,它将在应用程序出现故障时触发。 这些故障可能是文件不能正确加载,浏览器不能访问 cache manifest 文件,或 manifest 列出的一个或多个文件不存在等。 为了捕捉这些故障,只需为 error 事件添加一个事件侦听程序。

复制代码
window.applicationCache.addEventListener("error",onError);
function onError(e)
{
window.document.getElementById("loadedInfo").innerHTML = "Something went wrong while saving the files for offline use.";
}

数据库存储

HTML5 引入的最后一个存储类型是目前最处于不断变化之中的类型。 最初有一个 Web SQL 规范* ,但它现在已经不再使用。 现在,大多数人的精力已经转移到 Indexed Database API* 上,并且似乎这将是在关系型数据库中存储信息的出路。 Firefox 和 Chrome 均支持 IndexedDB,但由于相应的规范和支持功能均处于不断变化之中,所以它超出本文的讨论范围。 在将来某个时候,当这一状态改变时,我将进行相应的更新。

下一步阅读方向

在本文中,我探索了两种本地存储信息的主要方法。 第一种方法以 web 存储 API 的形式提供一些非常基本的数据存储技术。 利用这一方法,你可以在会话之外或为一个单一会话保存名称值对(name value pair)。 第二种方法,即应用程序 cache manifest,允许开发人员在本地机器上保存所有文件,以便可以在离线情形下访问它们。

关于 HTML5 存储 API 的更多信息,参见下列资源:

Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License +Adobe Commercial Rights

本文遵守知识共享—署名- 非商业性使用- 相同方式共享3.0 Unported License (Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License) 许可条件。 适合本文包含的代码范例、但超越本许可条件范围的其它许可条件能够在 Adobe 中查到。

查看原文: HTML5 存储 API 介绍

2011 年 9 月 14 日 00:002892

评论

发布
暂无评论
发现更多内容

区块链在农业领域能有什么用武之地?

CECBC区块链专委会

区块链技术 上链 农业链 三农

架构师训练营第二周学习总结

子豪sirius

设计原则之依赖倒置和接口隔离

林昱榕

极客大学架构师训练营 依赖倒置 设计原则 接口隔离

分布式唯一ID解析

Chank

架构师训练营第2周总结

Glowry

极客大学架构师训练营

Week 02- 作业:设计原则

dean

极客大学架构师训练营

依赖倒置原则

Halley

架构师训练营--第二周作业

_MISSYOURLOVE

极客大学架构师训练营 第二周作业

架构师训练营 - 第二周作业

Melo

架构师训练营-week2-作业

晓-Michelle

极客大学架构师训练营

架构师训练营-week2-作业

sljoai

作业 week

架构师训练营 -week2-总结

sljoai

架构师实现自己架构的主要手段

_MISSYOURLOVE

极客大学架构师训练营

架构师训练营第0期第二周作业

无名氏

依赖倒置原则 DIP 依赖反转原则

第 02 周 开发编程框架 命题作业

Jaye

软件设计原则

jason

软件设计原理

李海明

专栏

OOD设计原则之DIP

无心水

极客大学架构师训练营 面向对象设计原则 OOD SOLID

使用接口隔离原则优化 Cache 类的设计

李广富

第 2 周 - 学习总结

大海

极客大学架构师训练营

Flink on Zeppelin (3) - Streaming篇

章剑锋_Jeff

大数据 flink 流计算 Zeppelin

第 2 周 - 课后作业

大海

训练营第二周作业

Mr冰凉

极客大学架构师训练营--编程的未来 面向对象 依赖倒置原则 -- 第二次作业

John(易筋)

极客时间 极客大学 架构师 极客大学架构师训练营 依赖倒置原则

架构师训练营 Week 02 作业

Wancho

训练营第二周总结

Mr冰凉

架构师训练营第二周作业

子豪sirius

架构师训练营 - 第二周作业

zcj

极客大学架构师训练营

架构师训练营第二周作业 (3)

hiqian

架构师训练营第二周 - 总结

无心水

极客时间 架构师 极客大学架构师训练营 23种设计模式 面向对象设计原则

极客大学架构师训练营 编程的本质与未来 第三课 听课总结

John(易筋)

极客时间 极客大学 架构师 极客大学架构师训练营 编程的未来

2021 ThoughtWorks 技术雷达峰会

2021 ThoughtWorks 技术雷达峰会

HTML5 存储API介绍-InfoQ