IndexedDB 是一个事务型数据库系统,具体IndexedDB是什么,IndexedDB特点信息请阅读HTML5 IndexedDB。
IndexedDB API 是强大的,但对于简单的情况可能看起来太复杂。如果你更喜欢一个简单的 API,请尝试 localForage、dexie.js、PouchDB、idb、idb-keyval、JsStore 或者 lovefield 之类的库,这些库使 IndexedDB 对开发者来说更加友好。 |
使用 IndexedDB 的第一步是打开叫"testDB"数据库,没有的话则新建。使用indexedDB.open()方法。
var request = window.indexedDB.open("testDB", version);
version指定数据库版本,当你想要更改数据库格式(比如增加对象存储,非增加记录),必须指定更高版本,通过 versionchange 来更改
indexedDB.open()方法返回一个 IDBRequest 对象。这个对象通过三种事件error、success、upgradeneeded,处理打开数据库的操作结果。
当试图打开一个尚未被创建的数据库,或者如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件upgradeneeded。这时通过事件对象的target.result属性,拿到数据库实例。
request.onupgradeneeded = function(event){ //upgradeneeded 事件 };
error事件表示打开数据库失败。
request.onerror = function(event){ console.log("打开DB失败", event); };
success事件表示成功打开数据库。
request.onsuccess = function(event){ console.log("成功打开DB"); db = event.target.result; };
这时,通过request对象的result属性拿到数据库对象。
后续的操作主要在upgradeneeded事件的监听函数里面完成,因为这时版本从无到有,所以会触发这个事件。
request.onupgradeneeded = function(event){ console.log("Upgrading",event); db = event.target.result; var objectStore = db.createObjectStore("students", { keyPath : "rollNo"}); };
主键(key)是默认建立索引的属性。比如,数据记录是{ id: 1, name: '张三' },那么id属性可以作为主键。主键也可以指定为下一层对象的属性,比如{ foo: { bar: 'baz' } }的foo.bar也可以指定为主键。
如果数据记录里面没有合适作为主键的属性,那么可以让 IndexedDB 自动生成主键(自增长)。
var objectStore = db.createObjectStore("students", { autoIncrement: true });
新增数据指的是向对象仓库写入数据记录。这需要通过事务完成。可通过监听连接对象的success事件和error事件,了解是否写入成功
document.querySelector("#list .student .add").onclick = () => { transaction = db.transaction("students","readwrite"); objectStore = transaction.objectStore("students"); const sid = document.querySelector("#list .student .id").value; const str = document.querySelector("#list .student .str").value; if(sid !== "" && str !== "") { objectStore.add({rollNo: sid,value:str}); } else { confirm("主键和str不能为空") } //oncomplete能触发 transaction.oncomplete = function(event) { confirm("添加成功") }; transaction.onerror = function(event) { confirm("添加失败") }; }
异步事务使用数据库中的事件对象属性。所有的读取和写入数据均在事务中完成。由IDBDatabase发起事务,通过IDBTransaction 来设置事务的模式(例如:是否只读readonly或读写readwrite),以及通过IDBObjectStore来发起一个请求。同时你也可以使用它来中止事务。 Transactions 可使用以下三种模式:1、"readonly"允许读取数据,不改变。2、"readwrite"允许读取和写入现有数据存储,数据被改变。3、"versionchange"允许执行任何操作,包括删除和创建对象存储和索引。此模式是用于开始使用IDBDatabase (en-US) 的 setVersion() (en-US)方法更新版本号事务。这种模式的事务无法与其他事务并发运行。这种模式下的事务被称为“升级事务”。 |
IDBObjectStore.delete()方法用于删除记录。
document.querySelector("#list .student .romove").onclick = () => { transaction = db.transaction("students","readwrite"); objectStore = transaction.objectStore("students"); const sid = document.querySelector("#list .student .id").value; if(sid !== "") { objectStore.delete(sid); } else { confirm("主键不能为空") } transaction.oncomplete = function(event) { confirm("删除成功") }; transaction.onerror = function(event) { confirm("删除失败") }; }
删除数据和查找不存在的数据时时不会报错的,可自行写代码处理,可参考查找数据的方法。 |
修改数据要使用IDBObject.put()方法。
document.querySelector("#list .student .update").onclick = () => { transaction = db.transaction("students","readwrite"); objectStore = transaction.objectStore("students"); const sid = document.querySelector("#list .student .id").value; const str = document.querySelector("#list .student .str").value; if(sid !== "") { var request = objectStore.put({rollNo: sid,value:str}); request.onsuccess = function(event) { confirm("修改成功"); }; request.onerror = function(event) { confirm("修改发生错误"); }; } else { confirm("主键不能为空") } transaction.oncomplete = function(event) { console.log("事务成功"); }; transaction.onerror = function(event) { console.log("事务失败"); }; }
put()方法在修改不存在的数据时候会新增数据 |
查找数据要使用objectStore.get()方法。
document.querySelector("#list .student .search").onclick = () => { transaction = db.transaction("students","readwrite"); objectStore = transaction.objectStore("students"); const sid = document.querySelector("#list .student .id").value; if(sid !== "") { var request = objectStore.get(sid); request.onsuccess = function(event) { if (request.result==undefined) { confirm("查询不到数据!"); }else{ confirm("查询到的数据为:"+request.result.value); } }; request.onerror = function(event) { confirm("查询发生错误"); }; } else { confirm("主键不能为空") } transaction.oncomplete = function(event) { console.log("事务成功"); }; transaction.onerror = function(event) { console.log("事务失败"); }; }
本身indexedDB的delete()和get()方法在处理不存在的数据时时不会报错的,可自行处理。 |
deleteObjectStore()方法是要在upgradeneeded事件下处理的。删除表前要执行close()方法。
document.querySelector("#list .student .delete").onclick = () => { console.log('删除表开始'); version=version+1; db.close(); request = window.indexedDB.open("testDB",version); request.onerror = (event) => { console.error(event.target.error) }; request.onsuccess = (event) => { db = event.target.result; console.log('delet success') } request.onupgradeneeded = (event) => { db = event.target.result; db.deleteObjectStore("students"); // db.close(); //删除之后不需要再关闭,否则会报错 DOMException: The connection was closed objectStore = db.createObjectStore("students", { keyPath : "rollNo"}); confirm("删除表成功"); }; }
indexedDB.deleteDatabase()方法用于删除一个数据库,参数为数据库的名字。它会立刻返回一个IDBOpenDBRequest对象,然后对数据库执行异步删除。删除操作的结果会通过事件通知,IDBOpenDBRequest对象可以监听以下事件。
success:删除成功
error:删除报错
document.querySelector("#deleteBase_ss").onclick = () => { const DBDeleteRequest = window.indexedDB.deleteDatabase('testDB'); db.close(); DBDeleteRequest.onsuccess = (event) => { confirm("删除数据库成功"); }; DBDeleteRequest.onerror = (event) => { confirm("删除数据库失败"); }; }
更多案例请下载