IndexedDB概述
為什么要用IndexedDB?
1.大量數(shù)據(jù)儲存在客戶端,這樣可以減少從服務器獲取數(shù)據(jù)的次數(shù),直接從本地獲取數(shù)據(jù)。
2.現(xiàn)有的瀏覽器數(shù)據(jù)儲存方案,都不適合儲存大量數(shù)據(jù):
Cookie 的大小不超過4KB,且每次請求都會發(fā)送回服務器
LocalStorage 在 2.5MB 到 10MB 之間(各家瀏覽器不同)
...
IndexedDB是什么?
1.IndexedDB 就是瀏覽器提供的本地數(shù)據(jù)庫
2.IndexedDB 允許儲存大量數(shù)據(jù)(一般來說不少于 250MB),提供各種API,功能強大。
3.異步操作,防止大量數(shù)據(jù)的讀寫導致拖慢網(wǎng)頁的現(xiàn)象
indexedDB對象
1.數(shù)據(jù)庫

2.對象倉庫:每個數(shù)據(jù)庫包含若干個對象倉庫。它類似于關系型數(shù)據(jù)庫的表格。
3.數(shù)據(jù)記錄:對象倉庫保存的是數(shù)據(jù)記錄。
4.索引:為了加速數(shù)據(jù)的檢索,可以在對象倉庫里面,為不同的屬性建立索引。
5.事務:數(shù)據(jù)記錄的讀寫和刪改,都要通過事務完成。
6.指針

api的基本使用
1.打開數(shù)據(jù)庫:indexedDB.open()
IndexedDB.open()方法返回一個 IDBRequest 對象。這個對象通過三種事件error、success、upgradeneeded,處理打開數(shù)據(jù)庫的操作結(jié)果
打開數(shù)據(jù)庫的執(zhí)行順序:
數(shù)據(jù)庫存在 ? error/ success : upgradeneeded => error/ success
// 1.打開數(shù)據(jù)庫
openDB () {
return new Promise((resolve, reject) => {
let db
const request = this.indexedDB.open('databaseName', 1) // 事務對象 databaseName:數(shù)據(jù)庫的名字 version:數(shù)據(jù)庫的版本
request.onsuccess = function (event) {
db = event.target.result // 數(shù)據(jù)庫對象
console.log('數(shù)據(jù)庫打開成功')
resolve(db)
}
request.onerror = function (event) {
console.log('數(shù)據(jù)庫打開報錯')
}
request.onupgradeneeded = function (event) { // 數(shù)據(jù)庫創(chuàng)建或升級的時候會觸發(fā)
console.log('onupgradeneeded')
}
})
},
2.新建/升級數(shù)據(jù)庫:upgradeneeded 事件
request.onupgradeneeded = function (event) { // 數(shù)據(jù)庫創(chuàng)建或升級的時候會觸發(fā)
console.log('onupgradeneeded')
db = event.target.result // 數(shù)據(jù)庫對象
var objectStore
if (!db.objectStoreNames.contains('person')) {
objectStore = db.createObjectStore('person', { keyPath: 'id' }) // 創(chuàng)建表
// objectStore = db.createObjectStore('person', { autoIncrement: true }) // 創(chuàng)建表
objectStore.createIndex('name', 'name', { unique: false }) // 創(chuàng)建索引 可以讓你搜索任意字段
objectStore.createIndex('address', 'address', { unique: false })
objectStore.createIndex('nameAddr', ['name', 'address'], { unique: false })
objectStore.createIndex('flag', 'flag', { unique: false })
}
}
(1)objectStore = db.createObjectStore('person', { keyPath: 'id' })新建對象倉庫(即新建表),主鍵(key)是默認建立索引的屬性,比如,數(shù)據(jù)記錄是{ id: 1, name: '張三' },那么id屬性可以作為主鍵
(2)objectStore = db.createObjectStore('person', { autoIncrement: true })新建對象倉庫(即新建表),數(shù)據(jù)記錄里面沒有合適作為主鍵的屬性,那么可以讓 IndexedDB 自動生成主鍵
(3)objectStore.createIndex('flag', 'flag', { unique: false })創(chuàng)建索引,可以讓你搜索任意字段;三個參數(shù)分別為索引名稱、索引所在的屬性、配置對象(說明該屬性是否包含重復的值)
3.新增數(shù)據(jù):add()
// 2.新增數(shù)據(jù) db:數(shù)據(jù)庫實例 storename:倉庫名稱 data:數(shù)據(jù)
addData (db, storename, data) {
var request = db.transaction([storename], 'readwrite') // 事務對象 指定表格名稱和操作模式("只讀"或"讀寫")
.objectStore(storename) // 倉庫對象
.add(data)
request.onsuccess = function (event) {
console.log('數(shù)據(jù)寫入成功')
}
request.onerror = function (event) {
console.log('數(shù)據(jù)寫入失敗')
throw new Error(event.target.error)
}
},
(1)db.transaction([storename], 'readwrite')新建時必須指定表格名稱和操作模式("只讀"或"讀寫")。
4.查詢數(shù)據(jù)
(1)主鍵讀取數(shù)據(jù)
讀取數(shù)據(jù)也是通過事務完成。
下邊代碼中,objectStore.get()方法用于讀取數(shù)據(jù),參數(shù)是主鍵的值。
// 3.通過主鍵讀取數(shù)據(jù) storename:表名稱 key 主鍵值
getDataByKey: function (db, storename, key) {
return new Promise((resolve, reject) => {
var transaction = db.transaction([storename]) // 事務
var objectStore = transaction.objectStore(storename) // 倉庫對象
var request = objectStore.get(key)
request.onerror = function (event) {
console.log('事務失敗')
}
request.onsuccess = function (event) {
console.log('主鍵查詢結(jié)果: ', request.result)
resolve(request.result)
}
})
},
(2)游標查詢記錄,遍歷數(shù)據(jù)
遍歷數(shù)據(jù)表格的所有記錄,要使用指針對象 IDBCursor。
下面代碼中,新建指針對象的openCursor()方法是一個異步操作,所以要監(jiān)聽success事件。
// 4.通過游標查詢記錄 db 數(shù)據(jù)庫實例 storename 倉庫/表名稱
cursorGetData: function (db, storename) {
let list = []
var store = db.transaction(storename, 'readwrite') // 事務
.objectStore(storename) // 倉庫對象
var request = store.openCursor() // 指針對象
request.onsuccess = function (e) {
var cursor = e.target.result
if (cursor) { // 必須要檢查
list.push(cursor.value)
cursor.continue()// 遍歷了存儲對象中的所有內(nèi)容
} else {
console.log('游標查詢結(jié)果:', list)
}
}
},
(3)索引讀取數(shù)據(jù)
可以通過索引意義搜索任意字段,也就是說從任意字段拿到數(shù)據(jù)記錄。如果不建立索引,默認只能搜索主鍵。
假定新建表格的時候,對indexName字段建立了索引。
getDataByIndex: function (db, storename, indexName, indexValue) {
var store = db.transaction(storename, 'readwrite') // 事務
.objectStore(storename) // 倉庫對象
var request = store.index(indexName) // 索引對象
.get(indexValue)
request.onerror = function () {
console.log('事務失敗')
}
request.onsuccess = function (e) {
var result = e.target.result
console.log('索引查詢結(jié)果:', result)
}
},
(4)索引游標查詢記錄
與索引查詢的區(qū)別:
索引查詢:查詢滿足條件的第一條數(shù)據(jù)
索引和游標查詢:滿足條件的所有數(shù)據(jù)
// 6.通過索引游標查詢記錄 db:數(shù)據(jù)庫實例 storename 倉庫/表名稱 indexName:索引名 indexValue:索引值
cursorGetDataByIndex: function (db, storename, indexName, indexValue) {
let list = []
var store = db.transaction(storename, 'readwrite').objectStore(storename) // 倉庫對象
var request = store.index(indexName) // 索引對象
.openCursor(IDBKeyRange.only(indexValue)) // 指針對象
request.onsuccess = function (e) {
var cursor = e.target.result
if (cursor) { // 必須要檢查
list.push(cursor.value)
cursor.continue()// 遍歷了存儲對象中的所有內(nèi)容
} else {
console.log('游標索引查詢結(jié)果:', list)
}
}
request.onerror = function (e) {
}
}
5.更新數(shù)據(jù)
put()方法根據(jù)主鍵自動更新相應數(shù)據(jù)記錄
// 7.更新數(shù)據(jù) db:數(shù)據(jù)庫實例 tableName:表名稱 data:數(shù)據(jù)
updateData: function (db, storename, data) {
var request = db.transaction([storename], 'readwrite') // 事務對象
.objectStore(storename) // 倉庫對象
.put(data)
request.onsuccess = function () {
console.log('數(shù)據(jù)更新成功')
}
request.onerror = function () {
console.log('數(shù)據(jù)更新失敗')
}
},
6.刪除數(shù)據(jù)
(1)主鍵刪除
IDBObjectStore.delete()方法用于刪除記錄
// 8.刪除數(shù)據(jù) db:數(shù)據(jù)庫實例 tableName:表名稱 id:主鍵值
deleteData: function (db, storename, id) {
var request = db.transaction([storename], 'readwrite') // 事務
.objectStore(storename) // 倉庫對象
.delete(id)
request.onsuccess = function () {
console.log('數(shù)據(jù)刪除成功')
}
request.onerror = function () {
console.log('數(shù)據(jù)刪除失敗')
}
},
(2)索引和游標刪除指定的數(shù)據(jù)
匹配到滿足條件的數(shù)據(jù)后,cursor.delete()方法用于刪除數(shù)據(jù)記錄
// 9.通過索引和游標刪除指定的數(shù)據(jù) db:數(shù)據(jù)庫實例 storename:表名稱 indexName:索引名 indexValue:索引值
cursorDeleteData: function (db, storename, indexName, indexValue) {
var store = db.transaction(storename, 'readwrite').objectStore(storename) // 倉庫對象
var request = store.index(indexName) // 索引對象
.openCursor(IDBKeyRange.only(indexValue)) // 指針對象
request.onsuccess = function (e) {
var cursor = e.target.result
var deleteRequest
if (cursor) {
deleteRequest = cursor.delete()// 請求刪除當前項
deleteRequest.onerror = function () {
console.log('游標刪除該記錄失敗')
}
deleteRequest.onsuccess = function () {
console.log('游標刪除該記錄成功')
}
cursor.continue()
}
}
request.onerror = function (e) {
}
},
7.關閉數(shù)據(jù)庫
// 10.關閉數(shù)據(jù)庫 db:數(shù)據(jù)庫實例
closeDB: function (db) {
db.close()
console.log('數(shù)據(jù)庫已關閉')
},
8.刪除數(shù)據(jù)庫
注意要先關閉數(shù)據(jù)庫再刪除,否則刪除失敗
// 11.刪除數(shù)據(jù)庫 dbname:數(shù)據(jù)庫名稱
deletedb: function () {
var self = this
let deleteRequest = self.indexedDB.deleteDatabase('databaseName')
deleteRequest.onerror = function (event) {
console.log('刪除失敗')
}
deleteRequest.onsuccess = function (event) {
console.log('刪除成功')
}
},
小結(jié)
1.了解基本概念
2.API靈活使用
掌握這些就基本上掌握了IndexedDB的基本使用啦