【IndexedDB】基本使用

本文来源:本人在使用网页的StackEdit时,发现这东西不用网络,不用登陆,也能保存所有写过的文章,那么这些文章存在哪了呢?Cookie?LocalStorage?好像都不适合存太长的数据,然后发现了IndexedDB这个东西,随后对其进行了探索。

介绍

IndexedDB 是一种可以让你在用户的浏览器内持久化存储数据的方法。IndexedDB 为生成 Web Application 提供了丰富的查询能力,使我们的应用在在线和离线时都可以正常工作。

基本使用

创建数据库表以及索引

不同于关系型数据库,IndexedDB使用键值对的方式存储数据,且支持灵活的数据类型。结构如下图。

上图为我用来写MarkDown的StackEdit在本地存储的数据库表,可以看到其是采用键值对的方式存储数据的,Key列是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
<script>
//当该数据库不存在时会自动创建新库,后面的数字代表版本,当版本更新会进入onupgradeneeded对应的方法
var request = window.indexedDB.open("mydb",5);
request.onerror = function(event){
console.log('数据库打开报错');
};

var db;
request.onsuccess = function(event){
db = event.target.result;
console.log('数据库打开成功');
};

var mydb;
request.onupgradeneeded = function(event){
console.log('数据库更新成功');
mydb = event.target.result;
//创建person表,并设置id属性为主键
var objectStore = mydb.createObjectStore('person',{keyPath:'id'});
//创建索引
objectStore.createIndex('name', 'name', { unique: false });

};

</script>

创建结果

(数据是我后来插入的)


数据基本操作

我们可以把每次对数据库的操作看成是一个请求,然后通过该请求的onsuccess和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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<script>
//连接数据库,版本号可不写
var request = window.indexedDB.open("mydb",6);

const personData = [
{ id:"5",name:"asdf",value:"ccc" },
{ id:"6",name:"asdfasdf",value:"ccdsc" }
];
//如果数据库打开成功
var mydb;
request.onsuccess = function(event){
console.log('数据库打开成功');
mydb = event.target.result;

//这个对象很重要,大概所有的操作都要通过该对象进行
var objSto = mydb.transaction("person","readwrite").objectStore("person");

//删除请求,参数指定的是主键的值
var deleterequest = objSto.delete("5");
deleterequest.onsuccess = function(event){
console.log("数据删除成功");
};

/*
这里是添加数据模块,由于某行数据重复添加会出现错误导致后面的全部操作事务全部失败,故注释了
var addrequest = objSto.add({ id:"8",name:"asdfasdf",value:"ccdsc" });

addrequest.onsuccess = function(event){
console.log("add success!");
};

addrequest.onerror = function(event){
console.log("add failed!");
};
*/

//查询模块
var findrequest = objSto.get("2");
findrequest.onsuccess = function(event){
console.log("success find")
if(findrequest.result){
console.log("name:" + findrequest.result.name);
}
};
findrequest.onerror = function(event){
console.log("failed");
};

//遍历查询模块,使用到了游标
objSto.openCursor().onsuccess = function(event){
var cursor = event.target.result;
if (cursor){
console.log(cursor.key);
console.log(cursor.value.name);
cursor.continue();
}
};

//更新数据模块
var updaterequest = objSto.put({ id:"6",name:"呜哈哈",value:"ccdsc" });
updaterequest.onsuccess = function(event){
console.log("更新成功");
};

//索引查询
var index = objSto.index("name");
var indexrequest = index.get("asdf");
indexrequest.onsuccess = function(event){
var result = event.target.result;
if(result){
console.log(result);
}
};

/*
下面的代码可以把前面定义的personData里的数组插入库中
personData.forEach(function(person){
objSto.add(person);
})
*/
};
</script>

运行结果

这里可以看到,遍历还没结束的时候,下面的更新模块就运行完了,所以使用游标遍历要注意顺序问题。可能会出现某些问题。