HTML5的一大亮点是支持离线 Web 应用。
HTML5 把离线应用作为重点,这样 Web 应用能够与传统的客户端应用同场竞技,不再完全依赖网络。
开发离线 Web 应用需要几个步骤。
首先是确保应用知道设备是否能上网,以便下一步执行正确的操作。
然后,应用还必须能访问一定的资源(图像、JavaScript、CSS 等),只有这样才能正常工作。
最后,必须有一块本地空间用于保存数据,无论能否上网都不妨碍读写。
HTML5 及其相关的 API 让开发 离线应用成为现实。
离线检测
开发离线应用的第一步是要知道设备是在线还是离线,HTML5 为此定义了一个 navigator.onLine 属性,这个属性值为true表示设备能上网,值为false表示设备离线。
实际应用中,navigator.onLine 在不同浏览器间还有些小的差异。
IE6+和 Safari 5+能够正确检测到网络已断开,并将 navigator.onLine 的值转换为 false。
Firefox 3+和 Opera 10.6+支持 navigator.onLine 属性,但你必须手工选中菜单项“文件 → Web
开发人员(设置)→ 脱机工作”才能让浏览器正常工作。
Chrome 11 及之前版本始终将 navigator.onLine 属性设置为 true。这是一个有待修复的bug。
由于存在上述兼容性问题,单独使用 navigator.onLine 属性不能确定网络是否连通。即便如此,
在请求发生错误的情况下,检测这个属性仍然是管用的。
if (navigator.onLine){
//正常工作
} else {
//执行离线状态时的任务
}
除 navigator.onLine 属性之外,为了更好地确定网络是否可用,HTML5 还定义了两个事件: online 和 offline。
当网络从离线变为在线或者从在线变为离线时,分别触发这两个事件。这两个事件在 window 对象上触发。
EventUtil.addHandler(window, "online", function(){
alert("Online");
});
EventUtil.addHandler(window, "offline", function(){
alert("Offline");
});
应用缓存
HTML5 的应用缓存(application cache),或者简称为 appcache,是专门为开发离线 Web 应用而设计的。Appcache 就是从浏览器的缓存中分出来的一块缓存区。
要想在这个缓存中保存数据,可以使用一个描述文件(manifest file),列出要下载和缓存的资源。下面是一个简单的描述文件示例。
CACHE MANIFEST
#Comment
file.js
file.css
要将描述文件与页面关联起来,可以在html标签中的 manifest 属性中指定这个文件的路径,例如:
<html manifest="/offline.manifest" >
注意:这个描述文件的 MIME 类型必须是 text/cache-manifest。
虽然应用缓存的意图是确保离线时资源可用,但也有相应的 JavaScript API 让你知道它都在做什么。 这个 API 的核心是 applicationCache 对象,这个对象有一个 status 属性,属性的值是常量,表示应用缓存当前状态。
0:无缓存,即没有与页面相关的应用缓存。
1:闲置,即应用缓存未得到更新。
2:检查中,即正在下载描述文件并检查更新。
3:下载中,即应用缓存正在下载描述文件中指定的资源。
4:更新完成,即应用缓存已经更新了资源,而且所有资源都已下载完毕,可以通过 swapCache()
来使用了。
5:废弃,即应用缓存的描述文件已经不存在了,因此页面无法再访问应用缓存。
应用缓存还有很多相关的事件,表示其状态的改变。以下是这些事件。
checking:在浏览器为应用缓存查找更新时触发。
error:在检查更新或下载资源期间发生错误时触发。
noupdate:在检查描述文件发现文件无变化时触发。
downloading:在开始下载应用缓存资源时触发。
progress:在文件下载应用缓存的过程中持续不断地触发。
updateready:在页面新的应用缓存下载完毕且可以通过 swapCache()使用时触发。
cached:在应用缓存完整可用时触发。
一般来讲,这些事件会随着页面加载按上述顺序依次触发。
不过,通过调用 update()方法也可以手工干预,让应用缓存为检查更新而触发上述事件。
applicationCache.update();
update()一经调用,应用缓存就会去检查描述文件是否更新(触发 checking 事件),然后就像页面刚刚加载一样,继续执行后续操作。如果触发了 cached 事件,就说明应用缓存已经准备就绪,不会再发生其他操作了。如果触发了 updateready 事件,则说明新版本的应用缓存已经可用,而此时你需要调用 swapCache()来启用新应用缓存。
EventUtil.addHandler(applicationCache, "updateready", function(){
applicationCache.swapCache();
});
数据存储
Cookie
cookie不是我们讲述的重点,仅简单介绍。
cookie可以用于在客户端用于存储会话信息。该标准要求服务器对任意 HTTP 请求发送 Set-Cookie HTTP 头作为响应的一部分,其中包含会话信息。
例如:
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value
Other-header: other-header-value
每个域的cookie有个数以及存储空间的限制。
当超过单个域名限制之后还要再设置 cookie,浏览器就会清除以前设置的 cookie。
Web Storage
Web Storage 的目的是克服由 cookie 带来的一些限制。
Web Storage可以保证数据被严格控制在客户端上,也无须持续地将数据发回服务器。Web Storage 的两个主要目标是:
1、提供一种在 cookie 之外存储会话数据的途径;
2、提供一种存储大量可以跨会话存在的数据的机制。
最初的 Web Storage 规范包含了两种对象的定义:sessionStorage 和 globalStorage。
这两个对象在支持的浏览器中都是以 windows 对象属性的形式存在的;
支持这两个属性的浏览器包括 IE8+、 Firefox 3.5+、Chrome 4+和 Opera 10.5+。
sessionStorage 对象
sessionStorage 对象是Storage 类型的一个实例。
sessionStorage 对象存储特定于某个会话的数据,也就是该数据只保持到浏览器关闭。
存储在 sessionStorage 中的数据可以跨越页面刷新而存在,同时如果浏览器支持,浏览器崩溃并重启之后依然可用(Firefox 和 WebKit 都支持,IE 则不行)。
因为 seesionStorage 对象绑定于某个服务器会话,所以当文件在本地运行的时候是不可用的。
存储在 sessionStorage 中的数据只能由最初给对象存储数据的页面访问到,所以对多页面应用有限制。
存储数据的方法:
//使用方法存储数据
sessionStorage.setItem("name", "Nicholas");
//使用属性存储数据
sessionStorage.book = "Professional JavaScript";
读取数据的方法:
//使用方法读取数据
var name = sessionStorage.getItem("name");
//使用属性读取数据
var book = sessionStorage.book;
删除数据的方法:
//使用 delete 删除一个值——在 WebKit 中无效
delete sessionStorage.name;
//使用方法删除一个值
sessionStorage.removeItem("book");
sessionStorage 对象应该主要用于仅针对会话的小段数据的存储。如果需要跨越会话存储数据, 那么 localStorage 更为合适。
localStorage 对象
要访问同一个 localStorage 对象,页面必须来自同一个域名(子域名无效),使用同一种协议,在同一个端口上。
由于 localStorage 是 Storage 的实例,所以可以像使用 sessionStorage 一样来使用它。
存储在 localStorage 中的数据会保留到通过 JavaScript 删除或者是用户清除浏览器缓存。
storage 事件
对 Storage 对象进行任何修改,都会在文档上触发 storage 事件。当通过属性或 setItem()方法保存数据,使用 delete 操作符或 removeItem() 删除数据,或者调用 clear()方法时,都会发生该事件。这个事件的 event 对象有以下属性。
domain:发生变化的存储空间的域名。
key:设置或者删除的键名。
newValue:如果是设置值,则是新值;如果是删除键,则是 null。
oldValue:键被更改之前的值。
限制
对于 localStorage 而言,大多数桌面浏览器会设置每个来源 5MB 的限制。Chrome 和 Safari 对每个来源的限制是 2.5MB。而 iOS 版 Safari 和 Android 版 WebKit 的限制也是 2.5MB。
对 sessionStorage 的限制也是因浏览器而异。有的浏览器对 sessionStorage 的大小没有限制,但 Chrome、Safari、iOS 版 Safari 和 Android 版 WebKit 都有限制,也都是 2.5MB。IE8+和 Opera 对 sessionStorage 的限制是 5MB。
IndexedDB
Indexed Database API,或者简称为 IndexedDB,是在浏览器中保存结构化数据的一种数据库。IndexedDB 的思想是创建一套 API,方便保存和读取 JavaScript 对象,同时还支持查询及搜索。
IndexedDB 就是一个数据库,与 MySQL 或 Web SQL Database 等这些你以前可能用过的数据库类似。IndexedDB 最大的特色是使用对象保存数据,而不是使用表来保存数据。一个 IndexedDB 数据库,就是一组位于相同命名空间下的对象的集合。
IndexedDB 设计的操作完全是异步进行的。因此,大多数操作会以请求方式进行。这些操作会以异步的方式执行,然后如果成功则返回结果,如果失败则返回错误。差不多每一次 IndexedDB 操作,都需要你注册 onerror 或 onsuccess 事件处理程序,以确保适当地处理结果。
// 兼容各个浏览器的写法
var indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;