隨着瀏覽器功能加強,許多網站開始將大量數據保存在客戶端,從而減小從服務器獲取數據的操做,提升了響應速度。
cookie 因爲大小不超過 4kb,確定不合適。
LocalStorage 大小在 2.5 - 10 M間(不一樣瀏覽器不一樣,好比Chrome爲 5M),且不提供索引、查找慢,也不合適。
IndexedDB 就比較合適了,是瀏覽器提供的本地數據庫,它能夠被網頁腳本建立和操做。IndexedDB 容許儲存大量數據,提供查找接口,還能創建索引提升查詢效率。javascript
(1)採用鍵值對存儲。
IndexedDB 內部採用對象倉庫(object store)存放數據。全部類型的數據均可以直接存入,包括 JavaScript 對象。對象倉庫中,數據以"鍵值對"的形式保存。html
(2)異步處理。
IndexedDB 操做時採用異步處理,用戶能夠進行其它操做。vue
(3)支持事務。
IndexedDB 支持事務,即要麼完成、要麼失敗,不會出現完成一半的狀態。java
(4)存儲空間大、且支持二進制存儲。web
(1)數據庫(IDBDatabase 對象)
管理、存儲數據的倉庫。IndexedDB 數據庫有版本的概念。同一個時刻,只能有一個版本的數據庫存在。若是要修改數據庫結構(新增或刪除表、索引或者主鍵),只能經過升級數據庫版本完成。vue-cli
(2)對象倉庫(IDBObjectStore 對象)
每一個數據庫都包含若干對象倉庫。能夠理解爲一個個數據表。數據庫
(3)數據記錄
對象倉庫中存儲的即爲數據記錄,採用鍵值對保存。其中鍵惟一,值能夠爲任意類型。數組
(4)索引(IDBIndex 對象)
爲了提升查詢效率,能夠根據數據記錄的主鍵創建索引。瀏覽器
(5)事務(IDBTransaction 對象)
數據記錄的讀寫和刪改,都要經過事務完成。事務對象提供error、abort和complete三個事件,用來監聽操做結果。服務器
(6)操做請求(IDBRequest 對象)
(7)指針( IDBCursor 對象)
可用於遍歷數據。
(8)主鍵集合(IDBKeyRange 對象)
(1)項目目錄結構
使用vue-cli建立項目。參考:https://www.cnblogs.com/l-y-h/p/11241503.html
(2)完整代碼
此處,我將建立一個 「test」 數據庫, 其中有一個 「person」 表(對象倉庫) 【main.js】 import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app') 【App.vue】 <template> <div> <small>添加前請先打開數據庫(如數據庫不存在則執行建立過程)</small><br /><br /> <button @click="openDB">打開數據庫</button> <button @click="deleteDB">刪除數據庫</button><br /><br /> <button @click="closeDB">關閉數據庫</button><br /><br /> 姓名:<input type="text" id="name" v-model="name"><br /> 年齡:<input type="number" id="age" min=1 v-model="age"><br /> 性別: 男:<input type="radio" id="man" name="sex" value="male" v-model="sex"> 女:<input type="radio" id="woman" name="sex" value="female" v-model="sex"><br /> <button @click="add">添加數據</button> <button @click="get">獲取數據</button><br /> <button @click="foreach">遍歷數據</button><br /> <button @click="update">更新數據</button><br /> <button @click="remove">刪除數據</button><br /> <button @click="searchFromIndex">根據索引查數據</button><br /> </div> <!--App --> </template> <script> import indexedDB from './indexedDB.js' export default { data () { return { name: 'tom', age: '12', sex: 'male' } }, methods: { openDB() { indexedDB.openDB('test', 'person', 1) }, deleteDB() { indexedDB.deleteDB('test') }, closeDB() { indexedDB.closeDB('test') }, add() { indexedDB.add('person', {name: this.name, age: this.age, sex: this.sex}) }, get() { indexedDB.get('person') }, foreach() { indexedDB.foreach('person') }, update() { indexedDB.update('person', {id: 4, name: this.name, age: this.age, sex: this.sex}) }, remove() { indexedDB.remove('person', 4) }, searchFromIndex() { indexedDB.searchFromIndex('person', 'name', 'tom') } } } </script> <style> </style> 【indexedDB.js】 // 定義一個全局變量,用於保存數據庫鏈接(開發中應該不會這麼寫,此處只是幫助理解) let db = null; export default { // indexedDB兼容 indexedDB: window.indexedDB || window.webkitindexedDB || window.msIndexedDB || mozIndexedDB, // 打開數據庫 // dbname指的是 數據庫名, version 指的是 版本號 openDB(dbname, objectStoreName, version) { // 獲取當前數據庫版本號 var version = version || 1 // 獲取數據庫鏈接,若數據庫不存在,會建立數據庫(異步處理,根據狀況自動觸發下面三個事件) var request = this.indexedDB.open(dbname, version) // 獲取數據庫鏈接失敗 request.onerror = function(event) { console.log('IndexedDB數據庫打開錯誤') } // 獲取數據庫鏈接成功 request.onsuccess = function(event, callback) { db = event.target.result; if (callback && (typeof callback === 'function')) { callback(db) } if (db != null) { console.log('數據庫打開成功') } } // 建立新的儲存空間(當第一次建立數據庫、或者數據庫版本號變化時會觸發) request.onupgradeneeded = function(event) { console.log('數據庫版本變化') console.log('建立數據庫' + dbname) // 拿到數據庫鏈接的結果對象 db = event.target.result; // 判斷當前數據庫中表(對象倉庫)是否存在(注意此處是數據庫的表名,不是數據庫名) if (!db.objectStoreNames.contains(objectStoreName)) { // 建立對象倉庫,並設置主鍵自增 var objectStore = db.createObjectStore(objectStoreName, { keyPath: 'id', autoIncrement: true }) // 建立索引(根據須要建立) objectStore.createIndex('name', 'name', { unique: false }) objectStore.createIndex('age', 'age', { unique: false }) objectStore.createIndex('sex', 'sex', { unique: false }) } } }, // 刪除數據庫 deleteDB: function(dbname, callback) { // 刪除數據庫 var deleteQuest = this.indexedDB.deleteDatabase(dbname); // 成功刪除 deleteQuest.onerror = function() { console.log('刪除數據庫出錯' + event.target.message) } // 刪除失敗 deleteQuest.onsuccess = function() { if (callback && (typeof callback === 'function')) { callback() } console.log('刪除數據庫成功') } }, // 關閉數據庫 closeDB: function() { if (db != null) { db.close() db = null console.log("數據庫關閉") } }, // 添加數據 // 對象倉庫(表名),傳入的參數 add: function(objectStoreName, argument) { if (db != null) { console.log(db) // 執行事務,添加數據到對象倉庫(表) var request = db.transaction([objectStoreName], 'readwrite') .objectStore(objectStoreName) .add(argument); request.onsuccess = function(event) { console.log('數據寫入成功'); }; request.onerror = function(event) { console.log('數據寫入失敗'); } } }, // 獲取數據 // 對象倉庫(表名) get: function(objectStoreName) { if (db != null){ console.log(db) // 執行事務,從對象倉庫(表)中獲取全部數據 var request = db.transaction([objectStoreName], 'readwrite') .objectStore(objectStoreName).getAll() // 數據獲取失敗 request.onerror = function(event) { console.log('事務失敗') } //數據獲取成功 request.onsuccess = function(event) { if (request.result) { // 打印全部數據 console.log(request.result) } else { console.log('未得到數據記錄') } }; } }, // 遍歷數據 // 對象倉庫(表名) foreach: function(objectStoreName) { if (db != null){ console.log(db) // 執行事務,從對象倉庫(表)中獲取全部數據 var request = db.transaction([objectStoreName], 'readwrite') .objectStore(objectStoreName).openCursor() // 數據獲取失敗 request.onerror = function(event) { console.log('事務失敗') } //數據獲取成功 request.onsuccess = function(event) { let cursor = request.result if (cursor) { // 遍歷打印全部數據 console.log(cursor) console.log(cursor.key) console.log(cursor.value.name) console.log(cursor.value.age) console.log(cursor.value.sex) cursor.continue() } else { console.log('未得到數據記錄') } }; } }, // 更新數據(若數據存在,則覆蓋以前的數據,若數據不存在,則新增一個值) // 對象倉庫(表名) update: function(objectStoreName, argument) { if (db != null) { console.log(db) // 執行事務,添加數據到對象倉庫(表) var request = db.transaction([objectStoreName], 'readwrite') .objectStore(objectStoreName) .put(argument); request.onsuccess = function(event) { console.log('數據更新成功'); }; request.onerror = function(event) { console.log('數據更新失敗'); } } }, // 刪除數據(若數據不存在,則不會執行刪除操做) // 對象倉庫(表名) remove: function(objectStoreName, index) { if (db != null){ console.log(db) // 執行事務,從對象倉庫(表)中獲取全部數據 var request = db.transaction([objectStoreName], 'readwrite') .objectStore(objectStoreName).delete(index) // 數據獲取失敗 request.onerror = function(event) { console.log('事務失敗') } //數據獲取成功 request.onsuccess = function(event) { if (request.result) { // 遍歷打印全部數據 console.log(request.result) } else { console.log('未得到數據記錄') } }; } }, // 根據索引查值(若數據不存在,返回一個[]數組) // 對象倉庫(表名) searchFromIndex: function(objectStoreName, index, data) { if (db != null){ console.log(db) // 執行事務,從對象倉庫(表)中獲取全部數據 var request = db.transaction([objectStoreName], 'readonly') .objectStore(objectStoreName).index(index).getAll(data) // 數據獲取失敗 request.onerror = function(event) { console.log('事務失敗') } //數據獲取成功 request.onsuccess = function(event) { if (request.result) { // 遍歷打印全部數據 console.log(request.result) } else { console.log('未得到數據記錄') } }; } } }
(3)截圖:
step1:初始化頁面。
step2:點擊 打開數據庫。
step3:點擊添加按鈕
step4:改變數據後,再次添加
step5:獲取數據(控制檯打印)
step6:點擊遍歷數據按鈕
step7:更新數據
以更新id=4爲例,此時數據不存在,會新增。
當修改數據後,再次更新,則會覆蓋原數據。
step8:根據 name 查詢全部 爲 tom 的數據。
step9:刪除第4條數據(根據主鍵來刪,若主鍵不存在,則不會刪除)。
先獲取當前數據。
執行刪除後,會刪除id=4(id是主鍵)的數據。
step10:關閉、刪除數據庫
若先點擊 刪除按鈕,再點擊關閉按鈕,則刪除按鈕會等關閉按鈕執行後再執行。
此時,test數據庫被刪除。
(4)建立、打開數據庫
需使用 indexedDB.open() 方法,返回一個 IDBRequest 對象,並可能觸發三個事件(onsuccess 、onerror、onupgradeneeded )。
【格式:】
var request = window.indexedDB.open(databaseName, version);
【其中:】
databaseName :爲字符串,表示數據庫名,不可省略。
version : 爲當前數據庫版本,當數據庫不存在時,會建立數據庫,且默認爲1。
當數據庫存在時,若 version 大於當前數據庫版本,則會觸發數據庫升級操做。
當version 省略時,默認爲當前數據庫版本。
【可能會觸發的事件】
onsuccess 表示成功打開數據庫。
onerror 表示打開數據庫失敗。
onupgradeneeded 表示數據庫升級事件。當數據庫不存在,或者數據庫指定版本號大於當前版本時觸發。
【代碼:】
// 打開數據庫
// dbname指的是 數據庫名, version 指的是 版本號
openDB(dbname, objectStoreName, version) {
// 獲取當前數據庫版本號
var version = version || 1
// 獲取數據庫鏈接,若數據庫不存在,會建立數據庫(異步處理,根據狀況自動觸發下面三個事件)
var request = this.indexedDB.open(dbname, version)
// 獲取數據庫鏈接失敗
request.onerror = function(event) {
console.log('IndexedDB數據庫打開錯誤')
}
// 獲取數據庫鏈接成功
request.onsuccess = function(event, callback) {
db = event.target.result;
if (callback && (typeof callback === 'function')) {
callback(db)
}
if (db != null) {
console.log('數據庫打開成功')
}
}
// 建立新的儲存空間(當第一次建立數據庫、或者數據庫版本號變化時會觸發)
request.onupgradeneeded = function(event) {
console.log('數據庫版本變化')
console.log('建立數據庫' + dbname)
// 拿到數據庫鏈接的結果對象
db = event.target.result;
// 判斷當前數據庫中表(對象倉庫)是否存在(注意此處是數據庫的表名,不是數據庫名)
if (!db.objectStoreNames.contains(objectStoreName)) {
// 建立對象倉庫,並設置主鍵自增
var objectStore = db.createObjectStore(objectStoreName, {
keyPath: 'id',
autoIncrement: true
})
// 建立索引(根據須要建立)
objectStore.createIndex('name', 'name', {
unique: false
})
objectStore.createIndex('age', 'age', {
unique: false
})
objectStore.createIndex('sex', 'sex', {
unique: false
})
}
}
}
(5)添加數據
向對象倉庫(表)中寫入數據記錄。須要經過事務完成。
注意:
db以前已經聲明過全局了,這裏直接用(實際開發中應該不容許直接聲明,能夠經過回調函數來實現,有時間再補充)。
建立一個事務須要根據 對象倉庫名(表名)以及操做模式(readwrite, readonly),建立事務後,經過IDBTransaction.objectStore(name)方法,拿到 IDBObjectStore 對象,再經過表格對象的add()方法,向表格寫入一條記錄。
// 添加數據
// 對象倉庫(表名),傳入的參數
add: function(objectStoreName, argument) {
if (db != null) {
console.log(db)
// 執行事務,添加數據到對象倉庫(表)
var request = db.transaction([objectStoreName], 'readwrite')
.objectStore(objectStoreName)
.add(argument);
request.onsuccess = function(event) {
console.log('數據寫入成功');
};
request.onerror = function(event) {
console.log('數據寫入失敗');
}
}
},
(6)讀取數據
須要事務來操做。
能夠objectStore.get(index)、objectStore.getAll()方法用於讀取數據,參數index是主鍵的值。
// 獲取數據
// 對象倉庫(表名)
get: function(objectStoreName) {
if (db != null){
console.log(db)
// 執行事務,從對象倉庫(表)中獲取全部數據
var request = db.transaction([objectStoreName], 'readwrite')
.objectStore(objectStoreName).getAll()
// 數據獲取失敗
request.onerror = function(event) {
console.log('事務失敗')
}
//數據獲取成功
request.onsuccess = function(event) {
if (request.result) {
// 打印全部數據
console.log(request.result)
} else {
console.log('未得到數據記錄')
}
};
}
},
(7)遍歷數據
須要事務來操做。
遍歷數據表格的全部記錄,要使用指針對象 IDBCursor,使用objectStore.openCursor()獲取。
// 遍歷數據
// 對象倉庫(表名)
foreach: function(objectStoreName) {
if (db != null){
console.log(db)
// 執行事務,從對象倉庫(表)中獲取全部數據
var request = db.transaction([objectStoreName], 'readwrite')
.objectStore(objectStoreName).openCursor()
// 數據獲取失敗
request.onerror = function(event) {
console.log('事務失敗')
}
//數據獲取成功
request.onsuccess = function(event) {
let cursor = request.result
if (cursor) {
// 遍歷打印全部數據
console.log(cursor)
console.log(cursor.key)
console.log(cursor.value.name)
console.log(cursor.value.age)
console.log(cursor.value.sex)
cursor.continue()
} else {
console.log('未得到數據記錄')
}
};
}
},
(8)更新數據
須要事務來操做。
使用IDBObjectStore.put(index)方法能夠更新數據,若index存在則覆蓋,不然新增一個值。
// 更新數據(若數據存在,則覆蓋以前的數據,若數據不存在,則新增一個值)
// 對象倉庫(表名)
update: function(objectStoreName, argument) {
if (db != null) {
console.log(db)
// 執行事務,添加數據到對象倉庫(表)
var request = db.transaction([objectStoreName], 'readwrite')
.objectStore(objectStoreName)
.put(argument);
request.onsuccess = function(event) {
console.log('數據更新成功');
};
request.onerror = function(event) {
console.log('數據更新失敗');
}
}
},
(9)刪除數據
須要事務來操做。
IDBObjectStore.delete(index)方法用於刪除記錄,參數index是主鍵的值。
// 刪除數據(若數據不存在,則不會執行刪除操做)
// 對象倉庫(表名)
remove: function(objectStoreName, index) {
if (db != null){
console.log(db)
// 執行事務,從對象倉庫(表)中獲取全部數據
var request = db.transaction([objectStoreName], 'readwrite')
.objectStore(objectStoreName).delete(index)
// 數據獲取失敗
request.onerror = function(event) {
console.log('事務失敗')
}
//數據獲取成功
request.onsuccess = function(event) {
if (request.result) {
// 遍歷打印全部數據
console.log(request.result)
} else {
console.log('未得到數據記錄')
}
};
}
},
(10)使用索引
須要事務來操做。
根據創建的索引能夠很方便的查值。IDBObjectStore.index(index)方法用於索引查找,參數index是索引的值。
// 根據索引查值(若數據不存在,返回一個[]數組)
// 對象倉庫(表名)
searchFromIndex: function(objectStoreName, index, data) {
if (db != null){
console.log(db)
// 執行事務,從對象倉庫(表)中獲取全部數據
var request = db.transaction([objectStoreName], 'readonly')
.objectStore(objectStoreName).index(index).getAll(data)
// 數據獲取失敗
request.onerror = function(event) {
console.log('事務失敗')
}
//數據獲取成功
request.onsuccess = function(event) {
if (request.result) {
// 遍歷打印全部數據
console.log(request.result)
} else {
console.log('未得到數據記錄')
}
};
}
}
(11)刪除數據庫(會等事務結束再執行)
// 刪除數據庫
deleteDB: function(dbname, callback) {
// 刪除數據庫
var deleteQuest = this.indexedDB.deleteDatabase(dbname);
// 成功刪除
deleteQuest.onerror = function() {
console.log('刪除數據庫出錯' + event.target.message)
}
// 刪除失敗
deleteQuest.onsuccess = function() {
if (callback && (typeof callback === 'function')) {
callback()
}
console.log('刪除數據庫成功')
}
},
(12)關閉數據庫
// 關閉數據庫
closeDB: function() {
if (db != null) {
db.close()
db = null
console.log("數據庫關閉")
}
},
瀏覽器原生提供indexedDB對象,做爲開發者的操做接口。
用於打開數據庫。是一個異步操做,可是會當即返回一個IDBOpenDBRequest 對象。
打開一個名爲test、版本爲1的數據庫。若是該數據庫不存在,則會新建該數據庫。
var openRequest = window.indexedDB.open('test', 1);
觸發事件:
success:打開成功。
error:打開失敗。
upgradeneeded:第一次打開該數據庫,或者數據庫版本發生變化。
在success中,能夠經過openRequest.result屬性拿到已經打開的IndexedDB數據庫對象。
在upgradeneeded中,能夠傳入event,經過 event.target.result 拿到已經打開的IndexedDB數據庫對象。
用於刪除數據庫,是一個異步操做,但會馬上返回一個IDBOpenDBRequest對象。
刪除名爲test的數據庫。若數據庫不存在,不會報錯。
var DBDeleteRequest = window.indexedDB.deleteDatabase('test');
觸發事件:
success:刪除成功。
error:刪除失敗。
未完待續。。。
參考地址: https://wangdoc.com/javascript/bom/indexeddb.html