IndexedDB 基本使用
tags: Web
HTML5
JavaScript
IndexedDB
category: Front-End
description: HTML5 IndexedDB 基本使用
created_at: 2021/08/02 00:00:00
事前準備
- 處理過 JavaScript 事件
- 大概知道一些資料庫的知識
前言
最近想說如果有空閒時間就來拿技能競賽題目練一下手,發現說今年題目要求使用 IndexedDB
,所以想說就來記錄一下一些筆記。
目標
- 把
IndexedDB
功能稍微摸過一遍
開啟 Database
indexedDB.open(資料庫名稱, 版本)
- 這個東西回傳的不是
database
而是request
,要在從request
去取得database
- 版本的型態是
unsigned long long
,也就是說非負整數
IDBOpenDBRequest
把他展開來看 應該是類似這樣的東西 IndexedDB Open Database Request
這個東西主要就四個事件需要處理
- onsuccess
- onerror
- onblocked
- onupgradeneeded
onsuccess
一切正常就會觸發,可以在裡面取到 database
const dbRequest = indexedDB.open(dbName, version)
dbRequest.onsuccess = e => {
const db = e.target.result
console.log(db)
}
這樣你就會拿到一個 IDBDatabase
的物件,有一個比較重要的事件 onversionchange
,當資料庫的版本發生改變的時候該做的事情,通常是把資料庫連接 close
。
所以會變成下面這樣
const dbRequest = indexedDB.open(dbName, version)
dbRequest.onsuccess = e => {
const db = e.target.result
db.onversionchange = e => {
console.log('versionchange', e)
db.close()
}
}
加入一個 console.log()
可以知道他有沒有被觸發(之後會用到)。
onerror
這...應該很常見了..略
onblocked
上面有提到說 onversionchange
事件,這個是當你有多個頁籤,新的頁籤的資料庫需要升級,但是舊的頁籤還存在資料庫連線,就會進入到這邊(被阻擋block),所以可能就是提醒使用者說請關閉其他頁籤(?)
onupgradeneeded
這裡是資料庫版本發生變化的時候會觸發的事件,在還沒 Open
過,預設的版本是0,所以你版本不管填多少都會觸發進到這個事件(版本填0會被擋住,所以一定得>0)。
注意: 這裡也是你唯一可以修改資料庫結構的地方
dbRequest.onupgradeneeded = e => {
console.log('upgradeneeded', e)
const db = e.target.result
const store = db.createObjectStore(storeName, options)
}
這樣你就可以在你的資料庫裡面建立一個 store
,大概可以想像成資料表(table)
- createObjectStore options
- keyPath: 主鍵
Primary Key
存在value
物件中的路徑 - autoIncrement: Key 自動遞增,預設
false
設定 Index
store.createIndex(indexName, keyPath, options)
options
當中比較常用的是 unique
,如果設定為 true
將不允許重複
另外也有 multiEntry
可以設定。
- true: 如果
keyPath
的資料是Array
,會幫你攤平(方便搜尋),有興趣可以自己點進去看看發生什麼事 - false: 預設
新增預設資料
dbRequest.onupgradeneeded = e => {
const users = [{
name: 'user01'
}, {
name: 'user02'
}, {
name: 'user03'
}]
const db = e.target.result
const store = db.createObjectStore('users', {
keyPath: 'id',
autoIncrement: true
})
users.forEach(user => {
store.add(user)
})
}
這樣就會看到下圖的結果
想取得既有的 store
dbRequest.onupgradeneeded = e => {
const store = e.target.transaction.objectStore(storeName)
}
在來你就可以繼續對 store
進行操作。
檢查 store 存不存在
db.objectStoreNames.contains(storeName)
操作 Database
操作上都是基於 transaction
的,所以要先取得 transaction
,看你要對哪些 store
進行操作。
const transaction = db.transaction(storeNames, mode, options)
- storeNames: 可以是一個值,或是一個陣列
- mode:
readonly
orreadwrite
,預設為readonly
- options:
- durability:
- default: 預設值
- relaxed: 提供比較好的性能,適合用在臨時的資料,ex: 快取
- strict: 性能比較不好,但比較不會掉資料
- durability:
比較常用到的事件 oncomplete
, 當整個交易(transaction)完成會觸發
從 transaction 取得 store
const store = transaction.objectStore(storeName)
新增資料
const storeRequest = store.add(object)
實際上 store.add()
也是會回來一個 Request
的物件(IDBRequest),主要用的事件是 onsuccess
、onerror
,onerror
自然不用說,而onsuccess
則是執行成功會觸發。
另外也有 store.put()
方法,跟 add()
很像,只差在於說如果 Key
已經存在, add()
會觸發錯誤 DOMException: Key already exists in the object store.
,而 put()
則會蓋過去。
刪除資料
const storeRequest = store.delete(key)
取得資料
const request = store.get(id)
request.onsuccess = e => {
console.log(e.target.result)
}
列出所有資料
需要使用指標 Cursor
store.openCursor().onsuccess = e => {
const cursor = e.target.result
if (!cursor) return
console.log(cursor.key, cursor.value)
cursor.continue()
}
查詢資料
不論要從 Key
還是 Index
查詢,都可以用 IDBKeyRange
這個物件產生東西的來做 Query
MDN 上面有一張表格非常的詳細
有很多種就不一一舉例了,假設這裡範例使用 only
做查詢,假設 value
是你要查的東西
從 Key 查詢
const value = '...'
const keyRange = IDBKeyRange.only(value)
store.openCursor(keyRange).onsuccess = e => {
const cursor = e.target.result
if (!cursor) return
console.log(cursor.key, cursor.value)
cursor.continue()
}
從 Index 查詢
const value = '...'
const keyRange = IDBKeyRange.only(value)
store.index(indexName).openCursor(keyRange).onsuccess = e => {
const cursor = e.target.result
if (!cursor) return
console.log(cursor.key, cursor.value)
cursor.continue()
}
基本上就只差在有沒有 index()
這個函數。
更新及刪除資料
在你使用 Cursor
查詢到資料後,可以利用 Cursor
來做 Update
及 Delete
。
cursor.update({
...cursor.value, // 展開舊有資料,如果你還需要
newKey: newValue, // 新資料
})
或是刪除
cursor.delete()
兩者回來的東西一樣是 IDBRequest
,可以再繼續做處理。
總結
上面把 IndexedDB
基本上會用到的東西大概摸了一次,除了資料需要自己稍微做一下以外,其他照著弄應該都可以順利進行。