HTML5 的一个重要特性是本地数据持久性,它使用户能够在线和离线访问 Web 应用程序。IndexedDB支持本地存储大量对象,并使用健壮的数据访问机制检索数据。与 Web Storage 相比,IndexedDB 具有多个优势,其中包括索引、事务处理和健壮的查询功能。一个网站能够创建多个本地数据库,其中每个数据库都可以存放多个数据对象,一个对象中有存在多个数据集合,每个数据集合中有多个键值对。我们接下来一起学习一下关于IndexedDB的一些使用方法,包括数据的增删改查,以及索引和游标的使用方法。

### 创建数据库

```

首先我们创建一个名为testDB的数据库,之后我们的操作都是在这个数据库里面进行。open()可接受两个参数,一个为数据库名称,一个为数据库版本号,如果数据库不存在则创建。

var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;

//创建一个数据库
function createDb(){
var res=window.indexedDB.open('testDB');
res.οnerrοr=function(e){
alert("Database error:"+e.target.errorCode);
};
res.onsuccess=function(event){
alert("Database Create!");
};
}
```

![](https://s4.51cto.com/images/blog/202012/27/0e2685a5df0c88432a4b0bdeffe5a768.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)

### 删除数据库
```
//删除数据库
function deleteDataBase(){
var deleteDb=window.indexedDB.deleteDatabase("testDB");
deleteDb.onsuccess=function(e){
alert("deleteDb success!");
}
deleteDb.οnerrοr=function(e){
alert("deleteDb error:"+e.target.errorCode);
}
}
```

### 创建一个版本不同的数据库

这里有三个函数,onerror在打开或者创建数据库失败的时候执行,onsuccess在数据打开或者创建成功的时候执行,onupgradeneeded在数据库版本改变的时候执行。

```
//创建一个与版本号为2的数据库
function CreateVersion(){
var res=window.indexedDB.open('testDB',2);
res.οnerrοr=function(e){
alert("Database error:"+e.target.errorCode);
};
res.onsuccess=function(e){
alert("Database Create!");
};
res.onupgradeneeded=function(e){
alert("Database Version Changed!")
}
}
```

![](https://s4.51cto.com/images/blog/202012/27/3f84e232ae704dce311e5794271322e4.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)

### 创建一个存储对象

在这里我们创建了一个名称为students的存储对象,并且在创建的时候指定id字段作为数据存储的键值。

```
function createObjStore(){
var res=indexedDB.open('testDB',3);
res.onupgradeneeded=function(e){
var db=e.target.result;
if(!db.objectStoreNames.contains('students')){
db.createObjectStore('students',{keyPath:"id"});
}
alert('DB version changed');
};
}// createDb();// createObjStore();
```

![](https://s4.51cto.com/images/blog/202012/27/fbb27baa571a68fcecc82ce9e12e5da4.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)

### 增加数据

写了一个增加数据的函数,obj表示你的数据需要存储在那个存储对象中,dbname数据库名称,version数据库版本号,data要存放的数据。

```
function addData(obj,dbname,version,data){
var res =indexedDB.open(dbname,version);
res.onsuccess = function (evt) {
var db = evt.target.result; //使用事务
var store =db.transaction(obj, "readwrite").objectStore(obj);
store.add(data);
}
}
```

写到这里的时候遇到了一个错误”未捕获TypeError:无法使用indexeddb读取null的属性transaction”,关于这个错误的发生,是由于不了解异步javascript,而indexedDB就是异步的,可以参考以下这篇文章。

> Uncaught TypeError: Cannot read property ‘transaction’ of null with an indexeddb

>

> https://stackoverflow.com/questions/24256202/uncaught-typeerror-cannot-read-property-transaction-of-null-with-an-indexeddb

>

![](https://s4.51cto.com/images/blog/202012/27/f7543bc891b8214c2095efe31119b65b.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)

### 删除数据
```
//删除
function deleteData(storeName){
var req=window.indexedDB.open("testDB");
req.onsuccess=function(e){
var db=e.target.result;
//删除id为100的学生信息
var res=db.transaction(storeName,"readwrite").objectStore(storeName).delete("100");
res.onsuccess=function(){
console.log("delete success");
}
}
}//deleteData("students");
```
### 更新数据
```
function updateData(storeName){
var req=window.indexedDB.open("testDB");
req.onsuccess=function(e){
var db=e.target.result;
var store=db.transaction(storeName,"readwrite").objectStore(storeName);
//更新id为100的学生信息
store.get("100").onsuccess=function(evt){
var student=evt.target.result;
student.name="newtest";
var res=store.put(student);
res.onsuccess=function(){
console.log("success");
}
}
}

}//updateData("students");

```

![](https://s4.51cto.com/images/blog/202012/27/37ac40715c68c079e84f14aa97dd9cb5.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)

### 创建索引

在创建索引的时候会出现创建不成功情况,索引的创建需要在创建存储对象的时候进行创建,如果先创建了存储对象,然后通过获取到对象,再进行索引创建的时候,这样是不成功的,所以在这里我们重新创建了一个名称teachers的存储对象。在这里创建了三个索引’nameIndex’,’idIndex’,’ageIndex’,其中将idIndex的属性设置唯一。

```
//创建索引
function createIndex(){
var req=window.indexedDB.open('testDB',7);
req.onsuccess=function(e){
console.log("success");
}
req.onupgradeneeded=function(e){
var db=e.target.result;
var store=db.createObjectStore("teachers",{keyPath:"id"});
//创建索引
store.createIndex('nameIndex','name',{unique:false});
store.createIndex('idIndex','id',{unique:true});
store.createIndex("ageIndex","age",{unique:false});
}
}
//createIndex();//var data={"id":"0","name":"teacher0","age":"20"};
//addData("teachers","testDB",7,data);
```

![](https://s4.51cto.com/images/blog/202012/27/5ece65963df6b82fdcb833dd16cc6041.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)

### 索引查询
```
//根据索引查询
function findByIndex(obj,db){
var req=window.indexedDB.open("testDB");
req.onsuccess=function(e){
var db=e.target.result;
var store=db.transaction(obj).objectStore(obj);
var index=store.index("nameIndex");
//查询名字为“teacher0”的老师信息
index.get("teacher0").onsuccess=function(e){
var teacher=e.target.result;
console.log(teacher);
}
}
}//findByIndex("teachers","testDB");
```

![](https://s4.51cto.com/images/blog/202012/27/faef3f456df36b7b11a51d00e5431367.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)

### 游标

在这里我们利用游标来遍历数据库中存放的所有数据。

```
//游标
function findByCursor(stoeName){
var req=window.indexedDB.open("testDB");
req.onsuccess=function(e){
var db=e.target.result;
var store=db.transaction(stoeName).objectStore(stoeName);
//打开游标
var res=store.openCursor();
res.onsuccess=function(evt){
var cursor=evt.target.result;
if(cursor){
console.log(cursor.key,cursor.value);
cursor.continue();
}
}
}
}

// var data={"id":"1","name":"teacher1","age":"21"};/

/ addData("teachers","testDB",7,data);// findByCursor("teachers");

```

![](https://s4.51cto.com/images/blog/202012/27/deb2d00ca88236b9d1e5e8fdc8052482.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)

### 索引和游标
利用索引和游标查询了名称叫做”teacher1“的所有老师信息。
```
//索引和游标的结合
function findByIndexAndCursor(storeName){
var req=window.indexedDB.open("testDB");
req.onsuccess=function(e){
var db=e.target.result;
var store=db.transaction(storeName).objectStore(storeName);
var index=store.index("nameIndex"); //打开游标
var res=index.openCursor(IDBKeyRange.only('teacher1'));
res.onsuccess=function(evt){
var cursor=evt.target.result;
if(cursor){
console.log(cursor.key,cursor.value);
cursor.continue();
}
}
}
}
// var data={"id":"2","name":"teacher1","age":"23"};
// addData("teachers","testDB",7,data);// findByIndexAndCursor("teachers");
```

![](https://s4.51cto.com/images/blog/202012/27/caa855ffcc71f6314acf322fe1261c93.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)

参考文档:

HTML5本地存储——IndexedDB

使用 HTML5 IndexedDB API

https://www.ibm.com/developerworks/cn/web/wa-indexeddb/

Uncaught TypeError: Cannot read property ‘transaction’ of null with an indexeddb

https://stackoverflow.com/questions/24256202/uncaught-typeerror-cannot-read-property-transaction-of-null-with-an-indexeddb