IndexedDB
- 操作流程
- 打开数据库
- 新建数据库
- 新增数据
- 读取数据
- 遍历数据
- 更新数据
- 删除数据
- 使用索引
- 案例
- indexedDB对象
- indexedDB.open()
操作流程
打开数据库
使用IndexedDB 的第一步是打开数据库,使用indexedDB.open()方法
// 第一个参数是字符串,表示数据库的名字。如果指定的数据库不存在,就会新建数据库
// 第二个参数是整数,表示数据库的版本。如果省略,打开已有数据库时,默认为当前版本;新建数据库时,默认为1
var request = window.indexedDB.open(databaseName, version)
indexedDB.open() 方法返回一个IDBRequest对象。这个对象通过三个事件error、success、upgradeneeded,处理打开数据库的操作结果。
- error 事件
error 事件表示打开数据库失败。
request.onerror = function (event) {
console.log('数据库打开报错')
}
- success 事件
success 事件表示成功打开数据库。
var db
request.onsuccess = function (event) {
db = request.result
console.log('数据库打开成功')
}
// 这时,通过request 对象的 result属性拿到数据库对象。
- upgradeneeded 事件
如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件 upgradeneeded。
var db
request.onupgradeneeded = function (event) {
db = event.target.result
}
// 这时通过事件对象的 target.result 属性,拿到数据库实例
新建数据库
新建数据库与打开数据库是同一操作。如果指定的数据库不存在,就会新建。不同之处在于,后续的操作主要在 upgradeneeded 事件的监听函数里面完成,因为这时版本从无到有,所以会触发这个事件。
通常,新建数据库以后,第一件事是新建对象仓库(即新建表)。
// 数据库新建成功后,新增一张叫做person的表格,主键是id
request.onupgradeneeded = function (event) {
db = event.target.result
var objectStore = db.createObjectStore('person', { keyPath: 'id'})
}
// 更好的写法是先判断一下,这张表是否存在,如果不存在再新建。
request.onupgradeneeded = function (event) {
db = event.target.result
var objectStore
if (!db.objectStoreNames.contains('person')) {
objectStore = db.createObjectStore('person', {keyPath: 'id'})
}
}
主键(key)是默认建立索引的属性。比如,数据记录是 { id: 1, name: '张三’ },那么id 属性可以作为主键。主键也可以指定为下一层对象的属性,比如{foo: {bar: ‘baz’}}的foo.bar也可以指定为主键。
如果数据记录里面没有合适作为主键的属性,那么可以让IndexedDB自动生成主键。
// 指定主键为一个递增的整数
var objectStore = db.createObjectStore('person', {autoIncrement: true})
新建对象仓库以后,下一步可以新建索引。
request.onupgradeneeded = function (event) {
db = event.target.result
var objectStore = db.createObjectStore('person', { keyPath: 'id' })
objectStore.createIndex('name', 'name', {unique:false})
objectStore.createIndex('email', 'email', {unique:true})
}
// IDBObject.createIndex() 的三个参数分别为索引名称、索引所在的属性、配置对象(说明该属性是否包含重复的值)
新增数据
新增数据指的是向对象仓库写入数据记录。这需要通过事务完成。
// 写入数据需要新建一个事务。新建时必须指定表格名称和操作模式(“只读”或“读写”)。新建事务以后,通过 IDBTransaction.objectStore(name) 方法,拿到IDBObjectStore 对象,再通过表格对象的add()方法,向表格写入一条记录
function add() {
var request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.add({id:1, name: '张三', age: 24, email: '11@qq.com'})
request.onsuccess = function(event) {
console.log('数据写入成功')
}
request.onerror = function(event) {
console.log('数据写入失败')
}
}
add()
读取数据
读取数据也是通过事务完成。
// objectStore.get() 方法用于读取数据,参数是主键的值。
function read() {
var transaction = db.transaction(['person'])
var objectStore = transaction.objectStore('person')
var request = objectStore.get(1)
request.onerror = function(event) {
console.log('事务失败')
}
request.onsuccess = function(event) {
if (request.result) {
console.log('Name:'+request.result.name)
console.log('Age'+request.result.age)
console.log('Email'+request.result.email)
} else {
console.log('未获得数据记录')
}
}
}
read()
遍历数据
遍历数据表格的所有记录,要使用指针对象IDBCursor。
// 新建指针对象的 openCursor() 方法是一个异步操作,所以要监听success 事件
function readAll() {
var objectStore = db.transaction('person').objectStore('person')
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result
if (cursor) {
console.log(`Id:${cursor.key}`)
console.log(`Name${cursor.value.name}`)
console.log(`Age${cursor.value.age}`)
console.log(`Email${cursor.value.email}`)
cursor.continue()
} else {
console.log('没有更多数据')
}
}
}
readAll()
更新数据
更新数据要使用 IDBObject.put() 方法。
// put() 方法自动更新了主键为1的记录
function update() {
var request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.put({ id: 1, name: '李四', age: 35, email: '11@qq.com' })
request.onsuccess = function(event) {
console.log('数据更新成功')
}
request.onerror = function(event) {
console.log('数据更新失败')
}
}
update()
删除数据
IDBObjectStore.delete() 方法用于删除记录。
function remove() {
var request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.delete(1)
request.onsuccess = function(event) {
console.log('数据删除成功')
}
}
使用索引
索引的意义在于,可以让你搜索任意字段,也就是从任意字段拿到数据记录。
如果不建立索引,默认只能搜索主键(即从主键取值)。
// 假定新建表格的时候,对 name 字段建立了索引。
objectStore.createIndex('name', 'name', { unique: false })
然后从name找到对应的数据记录
var transaction = db.transaction(['person', 'readonly'])
var store = transaction.objectStore('person')
var index = store.index('name')
request.onsuccess = function(e) {
var result = e.target.result
if(result) {
// ...
} else {
// ...
}
}
案例
<template>
<div style="font-size:18px">
<el-button type="primary" @click="createdDB">新建</el-button>
<el-button @click="add">新增</el-button>
<el-button @click="read">读取</el-button>
<el-button @click="readAll">遍历数据</el-button>
<el-button @click="update">更新数据</el-button>
<el-button @click="remove">删除数据</el-button>
</div>
</template>
<script setup>
var request, db, db_table
function createdDB() {
request = window.indexedDB.open('person', '1')
request.onsuccess = function(res) {
db = res.target.result
console.log('成功', res)
}
request.onerror = function(error) {
console.log('失败', error)
}
request.onupgradeneeded = function(event) {
db = event.target.result
var objectStore
if (!db.objectStoreNames.contains('person')) {
objectStore = db.createObjectStore('person',{keyPath: 'id'})
}
objectStore.createIndex('name', 'name', {unique: false})
objectStore.createIndex('email', 'email', {unique: true})
}
}
function add() {
console.log(db)
request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.add({ id: 1, name: '张三', email: '11@qq.com' })
request.onsuccess = function(event) {
console.log('数据写入成功')
}
request.onerror = function(event) {
console.log('数据写入失败')
}
}
function read() {
var transaction = db.transaction(['person'])
var objectStore = transaction.objectStore('person')
request = objectStore.get(1)
request.onerror = function(event) {
console.log('事务失败', event)
}
request.onsuccess = function(event) {
if (request.result) {
console.log(`name:${request.result.name}`)
console.log(`email${request.result.email}`)
} else {
console.log('未获得数据记录')
}
}
}
function readAll() {
var objectStore = db.transaction('person').objectStore('person')
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result
if (cursor) {
console.log(`id:${cursor.key}`)
console.log(`name:${cursor.value.name}`)
console.log(`email:${cursor.value.email}`)
cursor.continue()
} else {
console.log('没有更多数据')
}
}
}
function update() {
request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.put({id: 1, name: 'haha', email: 'haha@qq.com'})
request.onsuccess = function(event) {
console.log('数据更新成功')
}
request.onerror = function(event) {
console.log('数据更新失败')
}
}
function remove() {
request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.delete(1)
request.onsuccess = function(event) {
console.log('数据删除成功')
}
}
</script>
indexedDB对象
indexedDB.open()
indexedDB.open() 方法用于打开数据库。这是一个异步操作,但是会立刻返回一个IDBOpenDBRequest 对象。
var openRequest = window.indexedDB.open('test', 1)
// 打开一个名为test,版本为1的数据库。如果该数据库不存在,则会新建该数据库。
// open() 方法的
// 第一个参数是数据库名称,格式为字符串,不可省略;
// 第二参数是数据库版本,是一个大于0的正整数(0报错),如果该参数大于当前版本,会触发数据库升级。第二个参数可省略,如果数据已存在,将打开当前版本的数据库;如果数据库不存在,将创建版本的数据库,默认版本为1.
打开数据库是异步操作,通过各种事件通知客户端。四种事件:
- success:打开成功
- error:打开失败
- upgradeneeded:第一次打开该数据库,或者数据库版本发生变化
- blocked:上一次的数据库连接还未关闭
第一次打开数据库时,会先触发 upgradeneeded 事件,然后触发 success 事件