基本概念
IndexedDB是一種在瀏覽器中持久存儲數(shù)據(jù)的方法,允許我們不考慮網(wǎng)絡(luò)可用性,創(chuàng)建具有豐富查詢能力的可離線web應(yīng)用程序。indexedDB對于存儲大量數(shù)據(jù)的應(yīng)用程序和不需要持久internet鏈接的應(yīng)用程序(例如郵件客戶端、待辦事項(xiàng)列或記事本)很有用
幾條重要的概念(需熟知)
首先IndexedDB是一個(gè)key-value型數(shù)據(jù)庫,可以使用一個(gè)key作為索引獲取或者存儲數(shù)據(jù)
IndexedDB是事務(wù)模式的數(shù)據(jù)庫。
其次IndexedDB是一種異步API
IndexedDB是面向?qū)ο蟮?。要求我們?yōu)橐环N數(shù)據(jù)創(chuàng)建一個(gè)對象倉庫(objectStore),只要這種數(shù)據(jù)是一個(gè)js對象即可。
5 . IndexedDB支持同源策略。
基本模式
IndexedDB 鼓勵(lì)使用的基本模式如下所示:
- 打開數(shù)據(jù)庫
- 在數(shù)據(jù)庫中創(chuàng)建一個(gè)對象倉庫(object store)
- 啟動一個(gè)事務(wù),并發(fā)送一個(gè)請求來執(zhí)行數(shù)據(jù)庫操作,如增加或提取數(shù)據(jù)等
- 通過監(jiān)聽正確類型的dom事件以等待操作完成
- 在操作結(jié)果是進(jìn)行一些操作
生成和構(gòu)建一個(gè)對象存儲空間
打開數(shù)據(jù)庫
let request = window.indexedDB.open('mydatabase');
如果數(shù)據(jù)庫不存在,上述命令會創(chuàng)建該數(shù)據(jù)庫。然后會觸發(fā)onupgradneeded事件。
成功/失敗處理函數(shù)
request.onerror = event => {
// do something
alert("打開本地indexedDB存儲失敗")
}
request.onsucess = event => {
// do something
db = event.target.result;
}
瀏覽器會在任意給定的web app首次嘗試打開一個(gè)indexedDB存儲時(shí)對用戶進(jìn)行提醒。用戶可以選擇允許訪問或者拒絕訪問。在瀏覽器的隱私模式下indexedDB是被完全禁止的。
創(chuàng)建和更新數(shù)據(jù)庫版本號
當(dāng)創(chuàng)建一個(gè)新的數(shù)據(jù)庫或者增加已經(jīng)存在的數(shù)據(jù)庫版本號時(shí),onupgrageneeded事件會被觸發(fā)。
request.onupgradeneeded = event => {
let db = event.target.result;
// 為該數(shù)據(jù)庫創(chuàng)建一個(gè)對象倉庫
let objStore = db.createObjectStore('name', {
keyPath: 'myKey'
});
}
// 假如說打開的是已經(jīng)存在的數(shù)據(jù)庫,那么觸發(fā)的是onsuccess函數(shù)
構(gòu)建數(shù)據(jù)庫
每當(dāng)一個(gè)值被存儲斤一個(gè)對象存儲空間時(shí),它會被和一個(gè)鍵相關(guān)聯(lián)。鍵的提供有以下幾種不同方法:

// 我們的客戶數(shù)據(jù)看起來像這樣。
const customerData = [
{ ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com" },
{ ssn: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org" }
];
request.onupgradeneeded = event => {
let db = event.target.result;
// 為該數(shù)據(jù)庫創(chuàng)建一個(gè)對象倉庫
// 建立一個(gè)對象倉庫來存儲我們客戶的相關(guān)信息,我們選擇 ssn 作為鍵路徑(key path)
// 因?yàn)?ssn 可以保證是不重復(fù)的
let objStore = db.createObjectStore('customers', {
keyPath: 'ssn'
});
// 姓名不唯一
objStore = objStore.createIndex('name', 'name', { unique: false})
// 郵箱唯一
objStore = objStore.createIndex('email', 'email', { unique: true})
}
事務(wù)操作
request.onupgradeneeded = event => {
let db = event.target.result;
// 為該數(shù)據(jù)庫創(chuàng)建一個(gè)對象倉庫
// 建立一個(gè)對象倉庫來存儲我們客戶的相關(guān)信息,我們選擇 ssn 作為鍵路徑(key path)
// 因?yàn)?ssn 可以保證是不重復(fù)的
let objStore = db.createObjectStore('customers', {
keyPath: 'ssn'
});
objStore = objStore.createIndex('name', 'name', { unique: false})
objStore = objStore.createIndex('email', 'email', { unique: true})
// 事務(wù)采用readwrite模式
objStore.transaction.oncomplete = event => {
let customerObjStore = db.transaction ("customers", "readwrite").ObjectStore("customers");
customerDate.forEach(customer => {
customerObjStore.add(customer);
});
}
}
增加、讀取和刪除數(shù)據(jù)
事務(wù)的三種模式:readonly,readwrite,versionchange
我們需要開啟一個(gè)事務(wù)才能對創(chuàng)建的數(shù)據(jù)庫進(jìn)行操作。
- versionchange: 如果想要修改數(shù)據(jù)庫模型或者接口,包括新建或者刪除對象倉庫或者索引,只能在versionchange事務(wù)中才能實(shí)現(xiàn)。
- readonly: 只讀
- readwrite: 讀寫
新增數(shù)據(jù)
let transaction(["customers"], "readwirite");
// 在所有數(shù)據(jù)添加完畢后的處理
transaction.oncomplete = function(event) {
alert("All done!");
};
transaction.onerror = function(event) {
// 不要忘記錯(cuò)誤處理!
};
let objectStore = transaction.objectStore("customers");
customerData.forEach(function(customer) {
var request = objectStore.add(customer);
request.onsuccess = function(event) {
// event.target.result === customer.ssn;
};
});
刪除數(shù)據(jù)
let request = db.transaction(["customers"], "readwrite")
.objectStore("customers")
.delete("444-44-4444");
request.onsuccess = function(event) {
// 刪除成功!
};
獲取數(shù)據(jù)
let transaction = db.transaction(["customers"]);
let objectStore = transaction.objectStore("customers");
let request = objectStore.get("444-44-4444");
request.onerror = function(event) {
// 錯(cuò)誤處理!
};
request.onsuccess = function(event) {
// 對 request.result 做些操作!
alert("Name for SSN 444-44-4444 is " + request.result.name);
};
更新數(shù)據(jù)庫中的記錄
let objectStore = db.transaction(["customers"], "readwrite").objectStore("customers");
var request = objectStore.get("444-44-4444");
request.onerror = function(event) {
// 錯(cuò)誤處理
};
request.onsuccess = function(event) {
// 獲取我們想要更新的數(shù)據(jù)
var data = event.target.result;
// 更新你想修改的數(shù)據(jù)
data.age = 42;
// 把更新過的對象放回?cái)?shù)據(jù)庫, put 方法進(jìn)行更新
let requestUpdate = objectStore.put(data);
requestUpdate.onerror = function(event) {
// 錯(cuò)誤處理
};
requestUpdate.onsuccess = function(event) {
// 完成,數(shù)據(jù)已更新!
};
};
瀏覽器調(diào)試

可以在圖中application-->indexedDB中進(jìn)行查看。
indexedDB與localstorage的區(qū)別
IndexedDB 的儲存空間比 LocalStorage 大得多,一般來說不少于 250MB,甚至沒有上限。