HTML5 IndexDB 用户本地化存储离线数据库的使用
了解的朋友,知道Web SQL曾是HTML5 离线数据存储的一种解决方案,它是一个基于SQLite 的离线数据库。但W3C 的 WebDatabase 规范最终选择主推IndexDB,对Web SQL则不再提供维护。
IndexDB是一个NoSQL类型的数据库,可在客户端进行大量结构化数据存储,能使用索引高效率搜索数据进行读写和管理操作。而且它的大多操作都是在异步模式下执行,能够让你使用高效的JavaScript事件驱动模块,减少等待,操作更加流畅。它也有为同步模式提供的API,但在碧海情天整理资料的时候据说还没有实现。
IndexedDB概述
1. IndexedDB存储形式为键值对:它可以存储一些复杂的对象,而键可以存储这些对象的属性值,并且可以使用索引对对象的属性进行快速检索。
2. IndexedDB建立在交互数据库模型的基础上:任何对IndexedDB的操作都发生一个交互操作(transaction,事务),如它提供的索引、表、游标等均与一个transaction关联,它定义了交互的生存时间与结束时抛出的事件,这样能很好的处理web程序在不同的tab窗口中实例的互操作。
3. IndexedDB的API大多是异步的:你可以向数据库发出操作的“请求”,当操作完成时会产生一个DOM事件,通过事件的类型会知道操作是否成功。
4. IndexedDB使用“请求”机制:操作对象会接收到DOM的success和failure事件,它也有相应的onsuccess和onerror的属性;对象还有readyState、result和errorCode属性来查看当前“请求”的状态,而result属性则根据不同的“请求”返回不同的结果。
5. IndexedDB 使用DOM事件机制来处理“请求”的结果:DOM事件的type属性提示操作是否成功,target属性指向发生“请求”的对象(大多数情况下是IDBRequest对象)。
6. IndexedDB工作基本流程:
1. 创建一个交互操作对象
2. 发送操作“请求”
3. 通过监听DOM事件等待操作完成
4. 处理“请求”结果
IndexedDB具体使用方法
1. 初始化声明
var dbName = "赵亮";
var dbVersion = 2.0;
var tablename = "碧海情天";
2. 初始并实例化IndexDB数据上下文
//定义一个IndexDB方法集合对象
var H5AppDB = {};
//实例化IndexDB数据上下文,这边根据浏览器类型来做选择
var indexedDB = window.indexedDB || window.webkitIndexedDB ||window.mozIndexedDB;
if ('webkitIndexedDB' in window) {
window.IDBTransaction = window.webkitIDBTransaction;
window.IDBKeyRange = window.webkitIDBKeyRange;
}
H5AppDB.indexedDB = {};
H5AppDB.indexedDB.db = null;
//错误信息,打印日志
H5AppDB.indexedDB.onerror = function (e) {
log.debug(e);
};
3. 打开数据库,初始化数据库,并创建存储对象
当创建数据库之后,需要添加数据,IndexedDB采用对象存储。首先要检查数据库的版本,若不是所期望的值,就要调用setVerion()方法来设置它的版本。
H5AppDB.indexedDB.open = function() {
//初始IndexDB
var request = indexedDB.open(dbName, dbVersion)
request.onsuccess = function(e) {
// Old api: var v = "2-beta"
log.debug("成功打开数据库: " + dbName)
H5AppDB.indexedDB.db = e.target.result
var db = H5AppDB.indexedDB.db
if (db.setVersion) {
console.log("旧版本号: " + db.setVersion)
if (db.version != dbVersion) {
var req = db.setVersion(dbVersion)
req.onsuccess = function() {
if (db.objectStoreNames.contains(tablename)) {
db.deleteObjectStore(tablename)
}
var store = db.createObjectStore(tablename, {
keyPath: "timeStamp"
})
var trans = req.result
trans.oncomplete = function(e) {
console.log("== 传输完成 ==")
H5AppDB.indexedDB.getAllTodoItems()
}
}
} else {
H5AppDB.indexedDB.getAllTodoItems()
}
} else {
H5AppDB.indexedDB.getAllTodoItems()
}
}
// 如果版本不一致,执行版本升级的操作
request.onupgradeneeded = function(e) {
log.debug("开始升级数据库。")
H5AppDB.indexedDB.db = e.target.result
var db = H5AppDB.indexedDB.db
if (db.objectStoreNames.contains(tablename)) {
db.deleteObjectStore(tablename)
}
var store = db.createObjectStore(tablename, {
keyPath: "timeStamp"
})
H5AppDB.indexedDB.getAllTodoItems()
}
request.onfailure = H5AppDB.indexedDB.onerror
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
4. 获取对象信息,并进行轮询读取,然后绑定到页面
H5AppDB.indexedDB.getAllTodoItems = function() {
var todos = document.getElementById("todoItems");
todos.innerHTML = "";
var db = H5AppDB.indexedDB.db;
var trans = db.transaction([tablename], "readwrite");
var store = trans.objectStore(tablename);
var keyRange = IDBKeyRange.lowerBound(0);
var cursorRequest = store.openCursor(keyRange);
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if ( !! result == false) return;
renderTodo(result.value);
result.
continue ();
};
cursorRequest.onerror = H5AppDB.indexedDB.onerror;
};
function renderTodo(row) {
var todos = document.getElementById("todoItems");
var li = document.createElement("li");
var a = document.createElement("a");
var t = document.createTextNode(row.text);
a.addEventListener("click", function() {
H5AppDB.indexedDB.deleteTodo(row.timeStamp);
}, false);
a.textContent = " [Delete]";
li.appendChild(t);
li.appendChild(a);
todos.appendChild(li);
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
5. 添加数据对象
H5AppDB.indexedDB.addTodo = function(todoText) {
var db = H5AppDB.indexedDB.db;
var trans = db.transaction([tablename], "readwrite");
var store = trans.objectStore(tablename);
var newArray = new Array("键1", "值1");
var data = {
"text": todoText,
"timeStamp": new Date().getTime(),
"obj": newArray
};
var request = store.put(data);
request.onsuccess = function(e) {
H5AppDB.indexedDB.getAllTodoItems();
};
request.onerror = function(e) {
log.debug("添加出错: ", e);
};
};
function addTodo() {
var todo = document.getElementById("todo");
H5AppDB.indexedDB.addTodo(todo.value);
todo.value = "";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
可以随意添加BJson格式的对象,体现NoSQl类型数据库的优越性。
IndexedDB采用最小化的错误事件处理,你不会看到很多类型的错误,它只提供一个错误的事件,可以通过event.target.errorCode来查看错误的信息,通常大多的错误都是用户不允许web操作本地的数据库,远程web所拥有的权限问题。
6. 删除数据对象(根据主键删除)
H5AppDB.indexedDB.deleteTodo = function(id) {
var db = H5AppDB.indexedDB.db;
var trans = db.transaction([tablename], "readwrite");
var store = trans.objectStore(tablename);
var request = store.delete(id);
request.onsuccess = function(e) {
H5AppDB.indexedDB.getAllTodoItems();
alert("删除成功");
};
request.onerror = function(e) {
log.debug("删除出错: ", e);
};
};
IndexedDB的安全性限制
IndexedDB 使用同源原则,这意味着它把存储空间绑定到了创建它的站点的源(典型情况下,就是站点的域或是子域),所以它不能被任何其他源访问。
要着重指出的一点是,IndexedDB 不适用于从另一个站点加载进框架的内容 (不管是用 frame 还是 iframe)。