一、离线检测
开发离线应用的第一个步骤是确定设备是在线还是离线,为此HTML5设置了一个navigator.onLine属性来表明浏览器是否可以上网。这个属性为true表示设备可以上网,值为false表示设备离线。
if(navigator.online){
//online
}
else{
//offline
}
除了navigator.online属性外,HTML5还专门设置了两个事件:online和offline,分别在设备上线和离线的时候触发。
window.addEventListener(‘online‘,function(){
alert(‘online‘);
},false);
window.addEventListener(‘online‘,function(){
alert(‘offline‘);
},false);
为了检测设备是否离线,要在页面加载后首先使用navigator.onLine检测页面的初始状态。然后通过online和offline事件检测网络设备的变化。当上述事件触发时navigator.onLine属性的值也会变化,不过要轮询监听该属性才能判断网络状态的变化。
二、应用缓存
HTML5的应用程序缓存 ( Application cache )是专门为离线web应用设计的。它从计算机缓存区中分出一部分来储存能够让程序离线运行的前端文件。需要下载的资源被写在一个 描述文件( manifest ) 中,下面是一个简单的描述文件事例:
CACHE MANIFEST
#Content
file.js
file.css
要将描述文件与页面关联起来,需要在html的manifest属性中声明描述文件的路径,如:
<html manifest="/offline.manifest">
这个文件的MIME类型必须是text/cache-manifest。扩展名推荐用.appcache。
在描述文件确定了需要下载的资源之后, 我们需要检测描述文件的更新情况。JS API为我们提供了一个applicationCache对象,它具有一个status属性储存了appCache的当前状态。
- 0:无缓存-没有与页面相关的应用缓存
- 1:闲置-应用缓存未更新
- 2:检查中-正在检查描述文件是否更新
- 3:下载中-更新完成
- 4:废弃-描述文件不存在了,不能获取应用缓存
同时,applicationCache还为状态的改变声明了事件。
- update:调动该事件手动查找更新
- checking:浏览器在为应用缓存查找更新时触发
- error:查找错误时触发
- noupdate:检查后发现描述文件无变化时触发
- downloading:开始下载应用缓存资源时触发
- progress:在下载应用缓存资源时不断的触发
- updateready:应用缓存已经更新完毕,并且可以通过swapCache()使用时触发
- cached:在应用缓存完整可用时触发
通常上述事件会顺序被触发。当我们使用applicationCache.update()手动发起更新时,checking()会首先被触发以检测描述文件的更新,当应用缓存(applicationCache)更新完毕时,updateready()被触发,此时需要我们手动调用swapCache()来启用新应用缓存。
applicationCache.update();
applicationCache.addEventListener(‘updateready‘,function(){
applicationCache.swapCache();
},false);
三、数据存储
随着Web应用的发展,我们需要获得在客户端储存用户数据的能力。常用的本地数据存储方式有三种,第一种就是Cookie,而第二种分别是HTML5支持的Web Storage和IndexedDB。
1. Cookie
1. 1 理解Cookie
服务器会对任意HTTP请求发送setCookie-HTTP头作为相应的一部分。
Set-Cookie: name=value
浏览器会储存这样的信息,并为之后的每个请求添加Cookie HTTP头将信息发送回服务器。
Cookie: name=value
通俗的理解,Cookie被储存在客户端上,在客户端向服务器发送数据时由浏览器作为请求头发送,以便于服务器验证客户来自于发送的哪个请求。
1.2 Cookie的格式
Cookie由名称,值,域,路径,失效时间和安全标志组成,其中域和路径代表了会向客户端发送Cookie的地址;失效时间表示cookie 何时应该被删除的时间戳(也就是,何时应该停止向服务器发送这个cookie)。默认情况下,浏览器会话结束时即将所有cookie 删除;不过也可以自己设置删除时间;而指定安全标志后,Cookie只有通过SSL连接才能传输。大体结构如下:
HTTP/1.1200 OK
Content-type: text/html
Set-Cookie: name=value; expires=Mon,22-Jan-0707:10:24 GMT; domain=.wrox.com; path=/; secure
Other-header: other-header-value
这个头指定了一个,叫做name的Cookie,它会在2007-1-22失效,同时它对与wrox.com域和所有子域都有效。因为设置了secure 标志,这个cookie 只能通过SSL 连接才能传输。尤其要注意,域、路径、失效时间和secure 标志都是服务器给浏览器的指示,以指定何时应该发送cookie。这些参数并不会作为发送到服务器的cookie 信息的一部分,只有名值对儿才会被发送。
1.3 Javascript Cookie操作
Javascript使用BOM的document.cookie来进行Cookie的读取、写入和删除。
varCookieUtil={
get:function(name){
var cookieName = encodeURIComponent("name")+"=",
cookieStart = document.cookie.indexOf(cookieName),
cookieValue =null;
if(cookieStart >-1){//存在name参数
cookieEnd = document.cookie.indexOf(";",CookieStart);
if(cookieEnd ==-1){//如果存在name参数却又没有‘;‘,说明name是最后一个
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent(document.cookie.substring(cookieStart+document.cookie.length, cookieEnd));
}
return cookieValue;
},
set:function(name, value, expires, domain, path, secure){//前两个是必填的
var cookieText = encodeURIComponent(name)+"="+ encodeURIComponent(value);
if(expires instanceof Date){//检测对象类型
cookieText +="; expires="+ expires.toGMTString();
}
if(domain){...}
},
unset:function(name){
this.set(name,"",newDate(0));
}
};
由于所有的 cookie 都会由浏览器作为请求头发送,所以在 cookie 中存储大量信息会影响到特定域的请求性能。 cookie 信息越大,完成对服务器请求的时间也就越长。尽管浏览器对 cookie 进行了大小限制,不过最好还是尽可能在 cookie 中少存储信息,以避免影响性能。
cookie 的性质和它的局限使得其并不能作为存储大量信息的理想手段,所以又出现了其他方法。
2. Web存储机制——Web Storage
Web Storage 定义了两种用于存储数据的对象: sessionStorage 和 localStorage。前者严格用于在一个浏览器会话中存储数据,因为数据在浏览器关闭后会立即删除;后者用于跨会话持久化数据并遵循跨域安全策略。
1. Storage类型
Storage 类型提供最大的存储空间(因浏览器而异)来存储名值对儿。 Storage 的实例与其他对象类似,有如下方法。
- clear() //删除所有值,firefox没有实现
- key(index) //获取index 处的名字
- setItem(name, value) //设置名字和值
- getItem(name) //获取name对应的值
- removeItem(name) //删除名值对
Storage只可储存字符串格式的值,我们可以使用 length 属性来判断有多少名值对儿存放在 Storage 对象中。但无法判断对象中所有数据的大小,不过 IE8 提供了一个 remainingSpace 属性,用于获取还可以使用的存储空间的字节数。
2. sessionStorage对象
sessionStorage对象只存储特定会话的数据,也就是它和cookie一样只保存数据到浏览器关闭。sessionStorage的数据可以跨页面刷新而存在,同时如果浏览器支持的话,也可以在浏览器崩溃后恢复数据。不过因为sessionStorage是绑定于某个服务器会话,所以当文件在本地运行的时候是不可用的。
由于 sessionStorage 对象其实是 Storage 的一个实例,所以可以使用 setItem()或者直接设置新的属性来存储数据。
//使用方法
sessionStorage.setItem("book","Professional Javascript");
sessionStorage.removeItem("book");
//使用属性
sessionStorage.book ="Professional Javascript";
delete sessionStorage.book;
sessionStorage 对象应该主要用于仅针对会话的小段数据的存储。如果需要跨越会话存储数据,那么 localStorage 更为合适。
3. localStorage对象
要访问同一个 localStorage 对象,页面必须来自同一个域名(子域名无效),使用同一种协议,在同一个端口上。由于localStorage对象是Storage类型的一个实例,所以我们完全可以通过Storage方法来访问该实例。
//使用方法存储数据
localStorage.setItem("name")="Pansy";
//使用属性存储数据
localStorage.book ="Professional Javascript";
//使用方法读取数据
var name = localStorage.getItem("name")
//使用属性读取数据
var book = localStorage.book;
//使用方法删除数据
localStorage.removeSItem("name");
//使用属性删除数据
remove localStorage.book;
如果不使用 removeItem() 或者 delete 删除,或者用户未清除浏览器缓存,存储 在globalStorage 属性中的数据会一直保留在磁盘上。这让 globalStorage 非常适合在客户端存储文档或者长期保存用户偏好设置。
3. IndexedDB
IndexedDB是在浏览器中储存 结构化数据 的一个数据库,是一个作为API宿主的全局对象。由于不同浏览器对于该对象有不同的描述方式,在使用该对象时,需要做出如下声明:
var indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB ||
window.webkitIndexedDB;
更多关于indexedDB本地化存储的知识请访问这里。
p.s. IE用户数据——持久化用户数据
在 IE5.0 中,微软通过一个自定义行为引入了持久化用户数据的概念。用户数据允许每个文档最多128KB 数据,每个域名最多 1MB 数据。要使用持久化用户数据,首先必须如下所示,使用 CSS 在某个元素上指定 userData 行为:
<divid="dataStore"style="behavior:url(#default#userData)"></div>
一旦元素使用了userData行为,就可以通过setAttribute()和e.save()向其中保存数据了。
<divstyle="behavior:url(#default#userData) id="dataStore"></div>
<script>
var dataStore = document.getElementById("dataStore");
dataStore.setAttribute("name","Pansy");
dataStore.setAttribute("book","Professional Javascript");
dataStore.save("bookInfo");
/*刷新页面*/
dataStore.load("bookInfo");
alert(dataStore.getAttribute("name"));//Pansy
/*删除存储数据*/
dataStore.removeAttribute("name");
dataStore.removeAttribute("book");
dataStore.save("bookInfo");
</script>