简单介绍

IndexedDb是html5新添加的特性,目地是使本地数据能够持久性,使用户能够在线和离线访问 Web 应用程序。关于HTML5 本地数据持久性存储,除了IndexedDb,还有 localstorage,和 sessionstrorage ,它们均支持使用一个简单的键值对来存储需要的数据,但对大量结构化数据的存储及高效检索却显的无能为力。

异步API

在IndexedDB中的大部分操作并不是我们常用的“调用——返回”的模式,而是“请求——响应”的模式,
比如打开数据库:

1
var request=window.indexedDB.open('myDB');

它的返回值并不是一个IndexedDb对象,而是一个请求体对象–IDBOpenDBRequest,其中包含了需要的IndexedDb对象,以及三个状态处理函数:

1
2
3
onerror: 请求失败的回调函数
onsuccess:请求成功的回调函数
onupgradeneeded:请求数据库版本变化的回调函数

因为是异步执行,所以请求执行完成,并不一定就能在返回的对象中获取到indexedDb对象句柄。为了避免出现错误,需要在回调中做出相应处理。

数据库

创建数据库

说明
open可以打开或者创建数据库,如果调用的时候,当前数据库已经存在,则会直接打开,如果不存在就会创建。数据库创建的时候,默认版本是1,如果在open的时候有传入这个参数,那么就会修改数据库的版本号,并调用onupgradeneeded这个回调。需要说明的是,不能打开比当前版本低的数据库,会触发onerror。

1
2
3
request = window.indexedDB.open(name[, version]);
or
request = window.indexedDB.open(name[, options])

参数

1
2
3
name:数据库的名称
version:数据库的版本,可选
option:包含版本及持久存储标志的对象,可选

返回值
一个IDBOpenDBRequest对象

实例

1
2
3
var request = window.indexedDB.open("toDoList"[, 4]);
or:
var request = window.indexedDB.open("toDoList"[, {version: 4, storage: "temporary"}]);

关闭/删除数据库

说明
关闭数据库可以直接调用数据库IDBDatabase对象的close方法,删除数据库使用indexedDB对象的deleteDatabase,如下:

1
2
IDBDatabase.close();
indexedDB.deleteDatabase(name);

参数

1
name:包含版本及持久存储标志的对象,可选

实例

1
2
3
4
5
6
7
8
9
var DBOpenRequest = window.indexedDB.open("toDoList", 4);
DBOpenRequest.onerror = function(event) {
};
DBOpenRequest.onsuccess = function(event) {
db = DBOpenRequest.result;
db.close();
}

数据存储对象(数据表)

说明
IndexedDb中的存储对象,相当于mySql中的数据表,一个数据库中可以创建多张数据表,在IndexedDb中也是一样,一个数据库中可以创建多个存储对象,称之为objectStore。

创建objectStore(数据表)

说明
使用IDBDatabase对象的createObjectStore方法:

1
IDBDatabase.createObjectStore(storeName [,"keyPath"] )

参数

1
2
storeName:存储对象的名字
keyPath:主健名,可选

返回值
返回创建出来的存储对象。

实例

1
IDBDatabase.createObjectStore('students',{keyPath:"id"});

删除objectStore(数据表)

说明
使用IDBDatabase对象的deleteObjectStore方法:

1
IDBDatabase.deleteObjectStore(storeName)

参数

1
storeName:要删除的存储对象

使用事务

说明
在IndexedDb中对存储对象中的数据所有操作都是基于事务的,事务提供了数据库操作的一个原子集合,对数据进行写入操作,同时也具有中止和提交工具。

事务模式

1
2
3
4
模式 描述
readonly 提供对某个对象存储的只读访问,在查询对象存储时使用。
readwrite 提供对某个对象存储的读取和写入访问权。
versionchange 提供读取和写入访问权来修改对象存储定义,或者创建一个新的对象存储。

默认的事务模式为 readonly,可以时刻打开多个 readonly 事务,但一次只能打开一个 readwrite 事务。因此,只有在数据更新时才考虑使用 readwrite 事务,其它情况下只用 readonly 。单独的(不同时打开其它类型事务时)versionchange 事务操作一个数据库或对象存储。可以在 onupgradeneeded 事件处理函数中使用 versionchange 事务用来创建、修改或删除一个对象存储。
创建事务
使用IDBDatabase中的transaction(storeName,mode)来创建事务。

1
IDBDatabase.transaction("students");

参数

1
2
storeName: 数据存储对象的名称,可以是多个,使用数组形式传入,此时模式不能是 readwrite
mode: 事务模式,可选,不传入是使用默认值

操作数据存储对象(数据表)

关于索引
对索引的使用使得在web端对大量数据高效检索,快速定位成为可能,这也是IndexedDb与其它html5的web存储的主要区别之一。在indexedDB中有两种索引,一种是自增长的int值;一种是keyPath,是自己指定索引列,常用的索引也是这种。

创建索引

说明
使用IDBObjectStore的createIndex(objectIndexName, objectKeypath, optionalObjectParameters)来创建:

1
IDBObjectStore.createIndex(IndexName, Keypath, ObjectParameters)

参数

1
2
3
indexName:要创建的索引名称
Keypath:创建当前索引使用的存储对象的列记录
ObjectParameters:当前索引可选的属性,为可选参数,其值可以有unique(唯一),multiEntry(可多选),locale

实例

1
2
var store = IDBDatabase.createObjectStore(sName,{"keyPath":keyName});
store.createIndex("nameIndex","name",{unique:true});

删除索引

说明
使用IDBObjectStore的deleteIndex(objectIndexName)来删除:

1
IDBObjectStore.deleteIndex(IndexName)

参数

1
indexName:要删除的索引名称

使用索引

说明
使用IDBObjectStore的index(objectIndexName)来获取索引IDBIndex 对象:

1
IDBObjectStore.index(IndexName)

参数

1
2
3
indexName:已存在的索引名称
<span style="color:green">返回值</span>:
IDBIndex对象,可以配合游标,检索数据。

实例

1
2
3
4
5
6
7
8
9
function getDataByIndex(dbobj,storeName){
var transaction=dbobj.transaction(storeName);
var store=transaction.objectStore(storeName);
var index = store.index("nameIndex");
index.get('张三').onsuccess=function(e){
var student=e.target.result;
console.log(student.id);
}
}

关于游标
IndexedDb的游标,有点类似数组的下标值,可以向前,向后遍历一个数组,甚至可以配合其它条件跳过一些数据。索引跟游标是分不开的,可以在建立索引的时候同时建立游标,然后就可以对数据进行遍历。

创建游标

说明
使用IDBObjectStore的openCursor(KeyRange, Direction)来创建:

1
IDBObjectStore.openCursor(KeyRange, Direction)

参数

1
2
KeyRange:游标的范围对象,即使用该游标时只会返回指定范围内的数据记录,可选,如果不送该值,则返回所有的数据记录。
Direction:游标遍历的方向,可选,如果不送该值,则默认为“next”。

KeyRange取值,有以下四种

1
2
3
4
5
6
7
8
// 只取得当前索引的值为 zhangsan 的数据
IDBKeyRange.only("zhangsan");
// 只取得当前索引的值大于 zhangsan,并且不包括 zhangsan 的数据
IDBKeyRange.lowerBound("zhangsan", true);
// 只取得当前索引的值小于 zhangsan,并且包括 zhangsan 的数据
IDBKeyRange.upperBound("zhangsan", false);
// 取得当前索引的值介于 zhangsan 和 lisi 之间,并且包括zhangsan,但不包括 lisi 的数据
IDBKeyRange.bound("zhangsan", "lisi", false, true);

Direction取值,有以下四种:

1
2
3
4
IDBCursor.NEXT //顺序循环
IDBCursor.NEXT_NO_DUPLICATE //顺序循环不重复
IDBCursor.PREV //倒序循环
IDBCursor.PREV_NO_DUPLICATE //倒序循环不重复

返回值
返回一个IDBRequest对像,其中包含数据记录的详细情况。

1
2
3
4
5
6
#### 遍历
类似数组中的自增或自减的操作,IndexedDb中,使用continue(),来进行游标的移动,直到没有数据返回了,返回为undefined结束。
### 兼容性
现在大部分支持Html5的浏览器都已支持IndexedDb,但在IE11、Edge中只是部分功能支持,Opera暂时不支持,安卓4.4以上全部支持。
通常在使用IndexedDb之前可以加部分前缀:

window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB ||window.msIndexedDB ;
window.IDBCursor = window.IDBCursor || window.webkitIDBCursor || window.msIDBCursor ;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction ;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange ;
```
具体可点击此处查询。

总结

IndexedDb是HTML5 的一个重要特性,它实现了本地数据的持久性,使用户能够在线和离线访问 Web 应用程序,也使移动应用程序更灵敏,使用的带宽更少,而且能够在低带宽场景中更高效地工作。在使用过程中,只有将索引,游标等功能相结合才能发挥出它最大的作用。

详细实例

可以点击此处进行在线演示。
所有代码以放在github上,点击此处下载。

本文地址: http://wsdever.github.io/2016/11/22/20161122/