[19天] IndexedDB初学笔记(一)
前言
MDN介绍:
IndexedDB
是一种底层 API,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象(blobs
))。该 API 使用索引实现对数据的高性能搜索。虽然 Web Storage 在存储较少量的数据很有用,但对于存储更大量的结构化数据来说力不从心。而IndexedDB
提供了这种场景的解决方案。
IndexedDB
是一个事务型数据库系统,类似于基于SQL
的 RDBMS。 然而,不像 RDBMS 使用固定列表,IndexedDB
是一个基于 JavaScript 的面向对象数据库。IndexedDB 允许您存储和检索用键索引的对象;可以存储结构化克隆算法支持的任何对象。您只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务。
接口
为了获取数据库的访问权限,需要在 window
对象的 indexedDB
属性上调用 open()
方法。该方法返回一个 IDBRequest
对象;异步操作通过在 IDBRequest
对象上触发事件来和调用程序进行通信。
连接数据库
-
IDBFactory
提供数据库访问。这是全局对象
indexedDB
实现的接口,因此是 API 的入口。 -
IDBOpenDBRequest
表示一个打开数据库的请求。
-
IDBDatabase
表示一个数据库连接。这是在数据库中获取事务的唯一方式。
接收和修改数据
-
IDBTransaction
表示一个事务。在数据库上创建一个事务,指定作用域(例如要访问的存储对象),并确定所需的访问类型(只读或读写)。
-
IDBRequest
处理数据库请求并提供对结果访问的通用接口。
-
IDBObjectStore
表示允许访问通过主键查找的 IndexedDB 数据库中的一组数据的对象存储区。
-
IDBIndex
也是为了允许访问 IndexedDB 数据库中的数据子集,但使用索引来检索记录而不是主键。这有时比使用 IDBObjectStore 更快。
-
IDBCursor
迭代对象存储和索引。
-
IDBCursorWithValue
迭代对象存储和索引并返回游标的当前值。
-
IDBKeyRange
定义可用于从特定范围内的数据库检索数据的键范围。
使用 IndexedDB
基本模式
-
打开数据库。
-
在数据库中创建一个对象仓库(object store)。
-
启动一个事务,并发送一个请求来执行一些数据库操作,像增加或提取数据等。
-
通过监听正确类型的 DOM 事件以等待操作完成。
-
在操作结果上进行一些操作(可以在 request 对象中找到)
打开数据库
let db
const request = window.indexedDB.open('lentonDB')
request.onsuccess = event => {
db = event.target.result
console.log(db)
}
request.onerror = event => {
console.error(event.target.errorCode)
}
open 请求不会立即打开数据库或者开始一个事务。 对 open() 函数的调用会返回一个我们可以作为事件来处理的包含 result(成功的话)或者错误值,
该 open 方法接受第二个参数,就是数据库的版本号。
数据库的版本决定了数据库架构,即数据库的对象仓库(object store)和他的结构。
如果数据库不存在,open
操作会创建该数据库,然后 onupgradeneeded
事件被触发,你需要在该事件的处理函数中创建数据库模式。
如果数据库已经存在,但你指定了一个更高的数据库版本,会直接触发 onupgradeneeded
事件,允许你在处理函数中更新数据库模式。
新建数据表与索引
let dataBase
let version = 1
const request = window.indexedDB.open('lentonDB', version)
request.onsuccess = event => {
dataBase = event.target.result
}
request.onerror = event => {
console.error(event.target.errorCode)
}
// 在version变更时,会触发该事件,可以在此时创建更新数据库结构
request.onupgradeneeded = event => {
dataBase = event.target.result
dofunc(dataBase)
}
function dofunc(db) {
const studentsTable = db.createObjectStore('students', {keyPath: 'id'})
studentsTable.createIndex('indexName', 'name', { unique: false });
}
新增数据
新增数据需要通过IDBTransaction
事务来完成, 写入数据需要新建一个事务, 新建时必须指定表格名称和操作模式("只读"或"读写")
add()
const data = [
{id: 1, name: 'lenton', age: 32},
{id: 2, name: 'tom', age: 35},
{id: 3, name: 'dived', age: 26},
]
const request = window.indexedDB.open('lentonDB', 1)
request.onsuccess = event => {
dofunc(event.target.result)
}
request.onerror = event => {
console.error(event.target.errorCode)
}
function dofunc(db) {
const transaction = db.transaction('students', 'readwrite')
const table = transaction.objectStore('students')
data.forEach(item => {
table.add(item)
})
}
根据主键id删除数据
delete()
const data = [
{id: 1, name: 'lenton', age: 32},
{id: 2, name: 'tom', age: 35},
{id: 3, name: 'dived', age: 26},
]
const request = window.indexedDB.open('lentonDB', 1)
request.onsuccess = event => {
dofunc(event.target.result)
}
request.onerror = event => {
console.error(event.target.errorCode)
}
function dofunc(db) {
const transaction = db.transaction('students', 'readwrite')
const table = transaction.objectStore('students')
table.delete(1)
}
根据主键修改数据
put()
const data = [
{id: 1, name: 'lenton', age: 32},
{id: 2, name: 'tom', age: 35},
{id: 3, name: 'dived', age: 26},
]
const request = window.indexedDB.open('lentonDB', 1)
request.onsuccess = event => {
dofunc(event.target.result)
}
request.onerror = event => {
console.error(event.target.errorCode)
}
function dofunc(db) {
const transaction = db.transaction('students', 'readwrite')
const table = transaction.objectStore('students')
table.put({id: 2, name: 'tom', age: 39})
}
根据主键查找数据
get()
const data = [
{id: 1, name: 'lenton', age: 32},
{id: 2, name: 'tom', age: 35},
{id: 3, name: 'dived', age: 26},
]
const request = window.indexedDB.open('lentonDB', 1)
request.onsuccess = event => {
dofunc(event.target.result)
}
request.onerror = event => {
console.error(event.target.errorCode)
}
function dofunc(db) {
const transaction = db.transaction('students', 'readwrite')
const table = transaction.objectStore('students')
const req = table.get(3)
req.onsuccess = event => {
console.log(event.target.result)
}
}
根据索引值查找数据
function dofunc(db) {
const transaction = db.transaction('students', 'readwrite')
const table = transaction.objectStore('students')
const index = table.index('name')
const req = index.get('tom')
req.onsuccess = event => {
console.log(event.target.result)
}
}
根据游标查询数据
function dofunc(db) {
const transaction = db.transaction('students', 'readwrite')
const table = transaction.objectStore('students')
const request = table.openCursor()
request.onsuccess = event => {
const cursor = event.target.result
if (cursor) {
console.log(cursor.value)
cursor.continue()
}
}
}
进行封装
IndexedDB
基于事务与事件,直接使用大量的回调与事件处理很麻烦。可以结合Promise
与 async await
进行一下封装再使用
未完待续...
参与讨论