所谓的离线web应用,就是在设备上不能上网的情况下仍然可以运行的应用。
开发离线web 应用的几个步骤:
1.首先是确保应用知道设备是否能上网
2.然后应用还必须能访问一定的资源
3.最后必须有一块本地的储存空间用于保存数据
离线检测 navigator.onLine
HTML5 定义了一个navigator.onLine属性。这个属性值为true表示设备可以上网,值为false表示设备离线。
if(navigator.onLine) {
//正常工作
} else {
//执行离线状态时的任务
}
除了navigator.onLine属性之外,HTML5还定义了两 个事件:online和offline。当网络从离线变为在线或者从在线 变为离线时,分别触发这 两个事件。
EventUtil.addHandler(window,"online",function(){
alert("Online");
});
EventUtil.addHandler(window,"offline",function(){
alert("Offline");
})
应用缓存
HTML5的应用缓存,或者简称为appcache,是专门为开发离线Web应用而设计的。
要想在这个缓存中保存数据,可以使用一个描述文件(manifest file),列出要下载和缓存的资源。
CACHE MANIFET
#Comment
file.js
file.css
要将描述的文件与页面关联起来,可以在<html>中的manifest属性中指定这个文件的路径,例如:
<html manifest="/offline.manifest">
这个API的核心是applicationCache对象,这个对象有一个status属性,属性值是常量:
0:无缓存
1: 闲置
2:检查中
3:下载中
4:更新完成。所有 资源下载完成后,可以通过swapCache()来使用了。
5:废弃
应用缓存还有很多相关的事件,表示其状态的改变:
checking:在浏览器为应用缓存查找更新时触发
error:在检查更新或下载资源期间发生错误时触发
noupdata:在检查描述文件发现文件无变化时触发
downloading:在开始下载应用缓存资源时触发
progress:在文件下载应用缓存的 过程中持续不断地触发
updateready:在页面新的应用缓存 下载完毕且可以通过swapCache()使用时触发
cached:在应用缓存完整可用时触发
applicationCache.updata();
updata()一经调用,应用缓存就会去检查描述文件是否更新。然后就像页面刚刚加载一样,继续执行后续操作。如果触发了cached事件,就说明应用缓存已经准备就绪,不会再发生其他操作。如果触发了updateready事件,则说明新版本的应用缓存已经可用,而此时要调用swapCache()来启用新应用缓存。
EventUtil.addHandler(applicationCache,"updateready",function(){
applicationCache.swapCache();
})
数据存储
Cookie
IE用户数据
Web存储机制
IndexedDB
Cookie
HTTP 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 HTTP头部信息发送回服务器,例如:
GET /index.html HTTP/1.1
Cookie: name=value
Other-header: other-header-value
限制
IE6及更多版本最多20个cookie
IE7之后的版本每个域名最多50个cookie
Firefox限制每个域最多50个cookie
Opera限制每个域最多30个cookie
Safar和Chrome没有硬性规定
cookie组成
名称:一个惟一确定名称
值:储存在cookie中的字符串值
域:cookie对于哪个域是有效的
路径:对于指定域中的哪个 路径,应用向服务器发送cookied
失效时间:表示cookie何时应用被删除的时间戳
安全标志:指定后,cookie只有在使用SSL连接的时候才会发送到服务器。
Javascript中的cookie
所有名字和值都是经过URL编码的,所以必须使用decodeURIComponent()
当用于设置值的时候,document.cookie属性可以设置为一个新的cookie字符串。
document.cookie = "name=Nicholas";
下面例子使用encodeURI-Component()
document.cookkie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas");
要给被创建的cookie指定额外的信息,可以如下:
document.cookkie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas") + ";domain=.wrox.com;path=/";
基本的cookie操作有三种:读取,写入和删除。如下:
var CookieUtil = {
get: function(name) {
var cookieName = encodeURIComponent(name) + "=",
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null;
if(cookieStart > -1) {
var cookieEnd = document.cookie.indexOf(";",cookieStart);
if(cookieEnd == -1){
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length,cookieEnd));
}
return cookieValue;
},
set: function(name, value, expires, path, domain, secure){
var cookieText = encodeURIComponent(name) + "=" +encodeURIComponent(value);
if(expires instanceof Date){
cookieText += "; expires=" + expires.toGMTString();
}
if(path){
cookieText += "; path=" + path;
}
if(domain){
cookieText += "; domain=" + domain;
}
if(secure){
cookieText += "; secure";
}
document.cookie = cookieText;
},
unset: function(name, path, domain, secure){
this.set(name, "", new Date(0), path, domain, secure);
}
}
//设置cookie
CookieUtil.set("name", "Nicholas");
CookieUtil.set("book", "Professional JavaScript");
//读取cookie
alert(CookieUtil.get(name)); //"Nicholas"
alert(CookieUtil.get(book)); //"Professional JavaScript"
//删除cookie
CookieUtil.unset("name");
CookieUtil.unset("book");
//设置cookie 包括它的路径,域,失效日期
CookieUtil.set("name", "Nicholas","/book/projs","www.wrox.com", new Date("January 1, 2011"));
//删除刚刚设置的cookie
CookieUtil.unset("name", "/book/projs", "www.wrox.com")
//设置安全的cookie
CookieUtil.set("name","Nicholas",null,null,null,true);
子cookie
为了绕开浏览器的单域名下的cookie限制数,可以使用一种称为子cookie的概念。它的格式如下 :
name=name1=value&name2=value2&name3=value3&name4=value4&name5=value5
获取子cookie方法有两种:get()和getAll()
设置子cookie方法有两种:set()和setAll()
删除子cookie方法有两种:unset(),unsetAll()
IE用户数据
微软通过一个自定义行为引入了持久化用户数据的概念。用户数据允许每个文档最多128KB数据,每个域名最多1MB数据。首先使用CSS在某个元素上指定userData行为:
<div style="behavior:url(#default#userData)" id="dataStore"></div>
<script type="text/javascript">
var dataStore = document.getElementById("dataStore");
dataStore.setAttribute("name", "Nichilas");
dataStore.setAttribute("book", "Professional JavaScript");
dataStore.save("BookInfo"); //保存到数据空间BookInfo
dataStore.load("BookInfo"); //获取数据
console.log(dataStore.getAttribute("name"));
console.log(dataStore.getAttribute("book"));
//可以使用removeAttribute()方法明确指定要删除的数据
dataStore.removeAttribute("name");
dataStore.removeAttribute("book");
dataStore.save("BookInfo");
</script>
Web存储机制
Web Storage的两个主要目的是:
1.提供一种在cookie之外的存储会话数据的途径
2.提供一种存储大量可以跨 会话存在的数据的机制
两种对象定义:sessionStorage和globalStorage
Storage类型
Storage类型提供最大的存储空间来存储名值对,Storage的实例与其他对象类似,有以下方法:
clear():删除所有值。
getItem:根据指定的名字name获取对应的值
key(index):获得index位置处的值的名字
removeItem(name):删除由name指定的名值对
setItem(name,value):为指定的name设置一个对应的值
sessionStorage对象
该对象存储特定于某个会话的数据,会cookie,在浏览器关闭后消失。
//使用方法存储数据
sessionStorage.setItem("name", "Nicholas");
//使用属性存储数据
sessionStorage.book = "Profesional Javascript";
//使用方法来读取数据
sessionStorage.getItem("name");
//使用属性存储数据
var book = sessionStorage.book;
还可以通过结束length属性和key()方法来迭代sessionStoragel中的值:
for (var i = 0, len = sessionStorage.length; i < len; i++) {
var key = sessionStorage.key(i);
var value = sessionStorage.getItem(key);
console.log(key + "=" + value);
}
globalStore对象
这个对象的目的是跨越会话存储数据。
//保存数据
globalStorage = ["wrox.com"].name = "Nichloas";
//获取数据
var name = globalStorage["wrox.com"].name;
//保存数据
globalStorage["www.wrex.com"].name = "Nichloas";
//获取数据
var name = globalStorage["www.wrex.com"].name;
localStorage对象
该对象可以持久保存客户端数据的方案取代了globalStorage。
//使用方法保存数据
localStorage.setItem("name", "Nicholas");
//使用属性保存数据
localStorage.book = "Professinal Javascript";
//使用方法读取数据
var name = localStorage.getItem("name");
//使用属性读取数据
var book = localStorage.book;
storage事件
对Storage对象进行任何修改,都会在文档上触发storage事件。
domain:发生变化的存储空间的域名
key:设置或者删除的键名
newValue:如果是设置值,则是新值,如果是删键,则是null
oldValue:键被更改之前的值
以下代码展示了如何侦听storage事件
EventUtil.addHandler(document,"storage",function(event){
alert("Storage changed for " + event.domain);
})
限制
localStorage:桌面浏览器会设置每个来源5MB,浏览 器2.5MB
sessionStorage:因浏览器而异,IE和Opera5MB,其他是2.5MB
IndexedDB
Indexed Database API,简称为IndexedDB,是在浏览器中保存数据的一种数据库。
var indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexDB || window.webkitIndexedDB ;
数据库
使用Index的第一步是打开它,即要把数据库名称传给indexedDB.open()。调用indexedDB.open()会返回一个IDBRequest对象,这个对象上可以添加onerror和onsuccess事件处理即可,如下示例:
var request,database;
request = indexedDB.open("admin");
request.onerror = function(event){
alert("Something bad happened while trying to open:" + event.target.errorCode);
}
request.onsuccess = function(event){
database = event.target.result;
}
对象存储空间
在建立 数据库后,下一步是使用对象存储空间。
假设要保存用户记录由用户名,密码等组成,可如下:
var user = {
username: "007",
firstName: "James",
lastName: "Bond",
password: "foo"
}
以下是为保存上述用户记录而创建对象存储空间的示例:
var store = db.createObjectStore("users",{keyPath: "username"});
有了存储空间的引用,接下来可以使用add()或put()方法来向其中添加数据。
//users 中保存着一批用户对象
var i = 0,
len = users.length;
while(i<len){
store.add(users[i++]);
}
如果想验证请求是否成功完成,可以把返回的请求对象保存一个变量中,然后再指定onerror或onsuccess事件处理程序
//users 中保存着一批用户对象
var i = 0,
request,
len = users.length;
while(i<len){
request = store.add(users(i++));
request.onerror = function(){
//处理程序
};
request.onsuccess = function(){
//处理成功
};
request.push(request);
}
创建了对象存储空间并向其中添加数据之后,就可以查询数据了
事务
在数据库对象上调用transactioon()方法可以创建事务。
var transaction = db.transaction();
var transaction = db.transaction("users",IDBTransaction.READ_WRITE);
取得了事务的索引后,使用objectStore()方法并传入存储空间,就可以访问特定的存储空间。
add(),put(),get(),delete(),clear()
var request = db.transaction(users).objectStore("users").get("007");
request.onerror = function(event){
alert("Did not get the object");
}
request.onsuccess = function(event){
var result = event.target.result;
alert(result.firstName);
}