离线应用与客户端存储

离线检测

navigator.onLine检测浏览器能否访问网络; 也可以监听online, offline事件来获取网络变化情况

1
2
3
4
5
6
window.online = function(event) {

}
window.offline = function(event) {

}

应用缓存

applicationCache专为离线web设计, applicationCache的status能够检测缓存情况

1
2
3
4
5
6
7
8
9
10
//将缓存与页面关联起来
<html manifest="/offline.manifest">

//缓存状况
console.log(applicationCache.status);

//监听缓存变化情况
applicationCache.updateready = function() {
applicationCache.swapCache();
}
1
2
3
4
5
6
7
8
//查看cookie
console.log(document.cookie)

//设置cookie
document.cookie = encodeURIComponent("test") + "=" + encodeURIComponent("value")

//删除cookie 其实就是让时间过期
document.cookie = encodeURIComponent("test") + "=" + encodeURIComponent("value") + "; expires=" + new Date(0)

子cookie

每个域设置的cookie是有上限的, 每条长度也有上限, 各浏览器各不一样; 我们可以设置子cookie增加cookie上限

1
2
//我们可以先获取parent, 先根据&split, 然后通过各sub获取对应的子cookie值
document.cookie = "parent=sub1=val1&sub2=val2"

IE用户数据

1
2
3
4
5
6
7
8
9
10
11
var dataStore = document.getElementById("dataStore");
dataStore.setAttribute("name", "test");
dataStore.setAttribute("book", "val");
dataStore.save("bookInfo");

//下一次加载页面 调用load 即可加载数据
dataStore.load("book")
//获取
dataStore.getAttribute("name");
//删除
dataStore.removeAttribute("name")

数据存储

浏览器对每个源存储的大小在 2.5M-5M之间

storage事件

setItem, clear, removeItem都会触发storage事件

1
2
3
window.addEventListener('storage', function(event) {
console.log(event.domain)
})

IndexedDB

数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//打开一个名为admin的数据库
var database;
var request = indexedDB.open("admin");
request.onsuccess = function(event) {
console.log("success")
database = event.target.result;
}
request.onerror = function(event) {
console.log(event.target.errorCode)
}

//给数据库设置版本号, 默认是没有版本号的
if (database.version != "1.0" && database.serVersion) {
request = database.serVersion("1.0");
request.onerror = function(event) {
console.log(event.target.errorCode);
}
request.onsuccess = function(event) {
console.log(database.version)
}
} else {
console.log(database.version)
}

对象存储空间

  • database.createObjectStore(表名, 指定主键)
  • store.add(obj) 添加数据
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var user = {
    username: "007",
    firstName: "James",
    lastName: "Bond",
    password: "foo"
    }

    var store = database.createObjectStore("users", {keypath: "username"})
    store.add(user)

事物

  • database.transaction([表名, …], 访问模式)
    1
    2
    3
    var transaction = database.transaction(["users", "anotherStore"], READ_WRITE)
    //获取相应的表 获取相应的数据
    transaction.objectStore("users").get("007")

使用游标查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var store = database.transaction(["users", "anotherStore"], READ_WRITE).objectStore("users"), value, updateRequest;
request.onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
if (cursor.key == "foo") {
value = cursor.value;
value.password = "magic"

updateRequest = cursor.update(value);
updateRequest.onsuccess = function() {}
updateRequest.onerror = function() {}
}
//游标移动到下一个
cursor.continue();
}
}

键范围

1
2
3
4
var IDBKeyRange = window.IDBKeyRange

//和上面的get("007") 功能类似
IDBKeyRange.only("007")

并发问题

当同一个来源的另一个标签页调用setVersion()时, 会触发onversionchange事件, 我们此时需要立即将数据库, 这样另一个页面的执行才能成功, 因为只有一个标签页使用数据库才能修改版本, 如果有其他tab开着数据库导致改变版本失败, 会触发onblock事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var database;
var request = indexedDB.open("admin");
request.onsuccess = function(event) {
console.log("success")
database = event.target.result;

database.onversionchange = function() {
database.close()
}

database.onblock = function() {
alert("请先关闭其他tab的数据库")
}
}

限制

数据库也是有大小限制的, 根据每个浏览器而不同, 大小在5mb-50mb之间