Book
Search…
Simple introduction
我们按照操作数据库的流程,来体验indexedDB的各种方法和对象。 code地址

链接数据库

1
if (!('indexedDB' in window)) return;
2
const DB = window.indexedDB.open('test','1');
Copied!
这个方法接受两个参数,第一个参数是字符串,表示数据库的名字。如果指定的数据库不存在,就会新建数据库。第二个参数是整数,表示数据库的版本。如果省略,打开已有数据库时,默认为当前版本;新建数据库时,默认为1。
indexedDB.open()方法返回一个 IDBRequest 对象。这个对象通过三种事件errorsuccessupgradeneeded,处理打开数据库的操作结果。
(1) error
error事件表示打开数据库失败。
1
DB.onerror = (err)=>{
2
console.log('数据库打开失败')
3
}
Copied!
(2) success
success事件表示打开数据库成功。
1
let DB = null;
2
dbRequest.onsuccess = ()=>{
3
DB = dbRequest.result;
4
console.log('数据库打开成功')
5
}
Copied!
可以通过request对象的result拿到数据库对象。 (3) upgradeneeded
如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件upgradeneeded
1
let DB = null;
2
dbRequest.onupgradeneeded = (event)=> {
3
db = event.target.result;
4
console.log('数据库升级')
5
}
Copied!

新建数据库/新建对象仓库

新建数据库与打开数据库是同一个操作。如果指定的数据库不存在,就会新建。不同之处在于第一次新建数据库的时候,因为这时版本从无到有,会触发upgradeneeded,所以后续的操作主要在upgradeneeded事件的监听函数里面完成。
通常,新建数据库以后,第一件事是新建对象仓库(即新建表)。
1
dbRequest.onupgradeneeded = (event)=> {
2
db = event.target.result;
3
console.log('数据库升级')
4
const objectStore = db.createObjectStore('videos',{keyPath:'id'});
5
}
Copied!
上面代码中,数据库新建成功以后,新增一张叫做videos的表格,主键是id。
更好的写法是先判断一下,这张表格是否存在,如果不存在再新建。
1
dbRequest.onupgradeneeded = (event) => {
2
db = event.target.result;
3
let objectStore;
4
if (!db.objectStoreNames.contains('videos')) {
5
objectStore = db.createObjectStore('videos', {
6
keyPath: 'id'
7
});
8
}
9
}
Copied!
主键(key)是默认建立索引的属性。比如,数据记录是{ id: 1, name: 'ind' },那么id属性可以作为主键。主键也可以指定为下一层对象的属性,比如{ matches: { id: '239' } }matches.id也可以指定为主键。
如果数据记录里面没有合适作为主键的属性,那么可以让 IndexedDB 自动生成主键。
1
var objectStore = db.createObjectStore(
2
'videos',
3
{ autoIncrement: true }
4
);
Copied!

新建索引

新建对象仓库以后,下一步可以新建索引。
1
dbRequest.onupgradeneeded = (event) => {
2
db = event.target.result;
3
let objectStore;
4
if (!db.objectStoreNames.contains('videos')) {
5
objectStore = db.createObjectStore('videos', {
6
keyPath: 'id'
7
});
8
objectStore.createIndex('channel_id', 'id', {
9
unique: true
10
})
11
}
12
}
Copied!
上面代码中,IDBObject.createIndex()的三个参数分别为索引名称、索引所在的属性、配置对象(说明该属性是否包含重复的值)。

新增数据

新增数据指的是向对象仓库写入数据记录。这需要通过事务完成。
1
function add(){
2
console.log('add')
3
const transaction = DB.transaction(['videos'],'readwrite');
4
const store = transaction.objectStore('videos');
5
store.add({
6
id: 'zLtKJ',
7
res: {
8
"result_code": 200,
9
"data": {
10
test:[]
11
},
12
"timestamp": 1552548880935
13
}
14
})
15
request.onsuccess = (event)=>{
16
console.log('write success')
17
}
18
request.onerror = (err)=>{
19
console.log('write error')
20
console.log(err)
21
}
22
transaction.oncomplete = ()=>{
23
console.log('transaction store success')
24
}
25
}
Copied!
上面代码中,写入数据需要新建一个事务。新建时必须指定表格名称和操作模式("只读"或"读写")。表名可以是一个也可以是多个(数组)。
新建事务以后,通过IDBTransaction.objectStore(name)方法,拿到 IDBObjectStore 对象,再通过表格对象的add()方法,向表格写入一条记录。
写入操作是一个异步操作,通过监听连接对象的success事件和error事件,了解是否写入成功。
当有很多写入操作时,也可以监听事务的complete事件,来了解事务是否完成。
当要添加数据的对象存储空间中已经存在有相同键的数据时,使用add()方法添加数据会报错误,而put()方法则会对现有数据进行更新,所以add()方法一般用于初始化数据,而put()方法用于更新数据。

读取数据

读取数据也是通过事务完成。
1
function read(){
2
const transaction = DB.transaction(['videos']);
3
const store = transaction.objectStore('videos');
4
const data = store.get('zLtKJ');
5
data.onsuccess = (event)=>{
6
if(event.target.result){
7
console.log(event.target.result);
8
}else{
9
console.log('no data')
10
}
11
}
12
data.onerror= (err)=>{
13
console.log('get data error')
14
console.log(err)
15
}
16
}
Copied!
上面代码中,objectStore.get()方法用于读取数据,参数是主键的值。

遍历数据

遍历数据表格的所有记录,要使用指针对象 IDBCursor,同样通过事务完成。
1
function map(){
2
const store = DB.transaction('videos').objectStore('videos');
3
store.openCursor().onsuccess = (event)=>{
4
const cursor = event.target.result;
5
if (cursor) {
6
console.log('Id: ' + cursor.key);
7
console.log('value: ' + cursor.value);
8
cursor.continue();
9
} else {
10
console.log('no more data');
11
}
12
}
13
}
Copied!
上面代码中,新建指针对象的openCursor()方法是一个异步操作,所以要监听success事件。

更新数据

当如果存在key的数据,不能在add数据,会报错,只能更新数据。
1
function update(){
2
const store = DB.transaction('videos','readwrite').objectStore('videos');
3
const request = store.put({
4
id:'zLtKJ',
5
res:{
6
data:{
7
test:[],
8
no:1
9
}
10
}
11
});
12
request.onsuccess = function (event) {
13
console.log('update success');
14
};
15
16
request.onerror = function (event) {
17
console.log('update fail');
18
}
19
}
Copied!
代码中,put()更新了id为zLtKJ的数据。

删除数据

1
function remove() {
2
var request = DB.transaction(['videos'], 'readwrite')
3
.objectStore('videos')
4
.delete('zLtKJ');
5
6
request.onsuccess = function (event) {
7
console.log('delete success');
8
};
9
}
Copied!

索引

索引的意义在于,可以让你搜索任意字段,也就是说从任意字段拿到数据记录。如果不建立索引,默认只能搜索主键(即从主键取值)。
假定新建表格的时候,对name字段建立了索引。
1
objectStore.createIndex('name', 'name', { unique: false });
Copied!
现在,就可以从name找到对应的数据记录了。
1
var transaction = db.transaction(['person'], 'readonly');
2
var store = transaction.objectStore('person');
3
var index = store.index('name');
4
var request = index.get('webkong');
5
6
request.onsuccess = function (e) {
7
var result = e.target.result;
8
if (result) {
9
// ...
10
} else {
11
// ...
12
}
13
}
Copied!
IndexedDB API是强大的,但对于简单的情况可能看起来太复杂。如果你更喜欢一个简单的API,可以使用一些第三方封装的库。 比如localForage, dexie.js, 和 ZangoDB等。
下面简单说一下localForage。