IndexedDB 學(xué)習(xí)

IndexedDB 學(xué)習(xí)

介紹

IndexedDB 是一個(gè)基于 JavaScript 的面向?qū)ο蟮氖聞?wù)型數(shù)據(jù)庫(kù)。其實(shí)對(duì)于在瀏覽器里存儲(chǔ)數(shù)據(jù),可以使用 cookies 或 LocalStorage,但它們都是比較簡(jiǎn)單的技術(shù),而 IndexedDB 提供了類似數(shù)據(jù)庫(kù)風(fēng)格的數(shù)據(jù)存儲(chǔ)和使用方式。

LocalStorage 與 IndexedDB 區(qū)別也適用場(chǎng)景

  • LocalStorage 是用 key-value 鍵值模式存儲(chǔ)數(shù)據(jù),它存儲(chǔ)的數(shù)據(jù)都是字符串形式。如果你想讓 LocalStorage存儲(chǔ)對(duì)象,你需要借助 JSON.stringify()能將對(duì)象變成字符串形式,再用 JSON.parse()將字符串還原成對(duì)象,就是專門(mén)為小數(shù)量數(shù)據(jù)設(shè)計(jì)的,所以它的 api 設(shè)計(jì)為同步的。

  • IndexedDB 很適合存儲(chǔ)大量數(shù)據(jù),它的 API 是異步調(diào)用的。IndexedDB 使用索引存儲(chǔ)數(shù)據(jù),各種數(shù)據(jù)庫(kù)操作放在事務(wù)中執(zhí)行。IndexedDB 甚至還支持簡(jiǎn)單的數(shù)據(jù)類型。IndexedDB 比 localstorage 強(qiáng)大得多,但它的 API 也相對(duì)復(fù)雜。對(duì)于簡(jiǎn)單的數(shù)據(jù),你應(yīng)該繼續(xù)使用 localstorage,但當(dāng)你希望存儲(chǔ)大量數(shù)據(jù)時(shí),IndexedDB 會(huì)明顯的更適合,IndexedDB 能提供你更為復(fù)雜的查詢數(shù)據(jù)的方式。

indexedDB 的特性

  • 對(duì)象倉(cāng)庫(kù)

有了數(shù)據(jù)庫(kù)后我們自然希望創(chuàng)建一個(gè)表用來(lái)存儲(chǔ)數(shù)據(jù),但 indexedDB 中沒(méi)有表的概念,而是 objectStore,一個(gè)數(shù)據(jù)庫(kù)中可以包含多個(gè) objectStore,objectStore 是一個(gè)靈活的數(shù)據(jù)結(jié)構(gòu),可以存放多種類型數(shù)據(jù)。也就是說(shuō)一個(gè) objectStore 相當(dāng)于一張表,里面存儲(chǔ)的每條數(shù)據(jù)和一個(gè)鍵相關(guān)聯(lián)。我們可以使用每條記錄中的某個(gè)指定字段作為鍵值(keyPath),也可以使用自動(dòng)生成的遞增數(shù)字作為鍵值(keyGenerator),也可以不指定。選擇鍵的類型不同,objectStore 可以存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)也有差異。

  • 事務(wù)性

在 indexedDB 中,每一個(gè)對(duì)數(shù)據(jù)庫(kù)操作是在一個(gè)事務(wù)的上下文中執(zhí)行的。事務(wù)范圍一次影響一個(gè)或多個(gè) object stores,你通過(guò)傳入一個(gè) object store 名字的數(shù)組到創(chuàng)建事務(wù)范圍的函數(shù)來(lái)定義。例如:db.transaction(storeName, 'readwrite'),創(chuàng)建事務(wù)的第二個(gè)參數(shù)是事務(wù)模式。當(dāng)請(qǐng)求一個(gè)事務(wù)時(shí),必須決定是按照只讀還是讀寫(xiě)模式請(qǐng)求訪問(wèn)。

  • 基于請(qǐng)求

對(duì) indexedDB 數(shù)據(jù)庫(kù)的每次操作,描述為通過(guò)一個(gè)請(qǐng)求打開(kāi)數(shù)據(jù)庫(kù),訪問(wèn)一個(gè) object store,再繼續(xù)。IndexedDB API 天生是基于請(qǐng)求的,這也是 API 異步本性指示。對(duì)于你在數(shù)據(jù)庫(kù)執(zhí)行的每次操作,你必須首先為這個(gè)操作創(chuàng)建一個(gè)請(qǐng)求。當(dāng)請(qǐng)求完成,你可以響應(yīng)由請(qǐng)求結(jié)果產(chǎn)生的事件和錯(cuò)誤。

  • 異步

在 IndexedDB 大部分操作并不是我們常用的調(diào)用方法,返回結(jié)果的模式,而是請(qǐng)求—響應(yīng)的模式,所謂異步 API 是指并不是這條指令執(zhí)行完畢,我們就可以使用 request.result 來(lái)獲取 indexedDB 對(duì)象了,就像使用 ajax 一樣,語(yǔ)句執(zhí)行完并不代表已經(jīng)獲取到了對(duì)象,所以我們一般在其回調(diào)函數(shù)中處理。

幾個(gè)概念

  • IDBFactory:數(shù)據(jù)庫(kù)工廠,負(fù)責(zé)打開(kāi)或者創(chuàng)建數(shù)據(jù)庫(kù)
    • IDBFactory.open 方法發(fā)送一個(gè)打開(kāi)或者創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)的請(qǐng)求
    • IDBFactory.deleteDatabase 方法: 發(fā)送一個(gè)刪除數(shù)據(jù)庫(kù)的請(qǐng)求
  • IDBDatabase: 數(shù)據(jù)庫(kù)
    • IDBDatabase.close 方法關(guān)閉數(shù)據(jù)庫(kù)。
    • IDBDatabase.createObjectStore 方法創(chuàng)建 store,相當(dāng)于表
    • IDBDatabase.transaction 開(kāi)啟一個(gè)事務(wù)。
  • IDBIndex:數(shù)據(jù)庫(kù)表的索引
  • IDBObjectStore:數(shù)據(jù)庫(kù)表
  • IDBTransaction:事務(wù)
  • IDBRequest:機(jī)會(huì)是所有 indexedDB 操作的返回值,indexedDB 操作請(qǐng)求
    • IDBRequest.result 結(jié)果
    • IDBRequest.onerror 異常事件
    • IDBRequest.onsuccess 成功的事件

快速入門(mén) demo

  • 打開(kāi)數(shù)據(jù)庫(kù)實(shí)例。
var db; // 全局的indexedDB數(shù)據(jù)庫(kù)實(shí)例。

//1\. 獲取IDBFactory接口實(shí)例(文檔地址: https://developer.mozilla.org/en-US/docs/Web/API/IDBFactory)
var indexedDB =
  window.indexedDB ||
  window.webkitIndexedDB ||
  window.mozIndexedDB ||
  window.msIndexedDB;

if (!indexedDB) {
  console.log('你的瀏覽器不支持IndexedDB');
}

// 2\. 通過(guò)IDBFactory接口的open方法打開(kāi)一個(gè)indexedDB的數(shù)據(jù)庫(kù)實(shí)例
// 第一個(gè)參數(shù): 數(shù)據(jù)庫(kù)的名字,第二個(gè)參數(shù):數(shù)據(jù)庫(kù)的版本。返回值是一個(gè):IDBRequest實(shí)例,此實(shí)例有onerror和onsuccess事件。
var IDBOpenDBRequest = indexedDB.open('demoDB', 1);

// 3\. 對(duì)打開(kāi)數(shù)據(jù)庫(kù)的事件進(jìn)行處理

// 打開(kāi)數(shù)據(jù)庫(kù)成功后,自動(dòng)調(diào)用onsuccess事件回調(diào)。
IDBOpenDBRequest.onsuccess = function(e) {};

// 打開(kāi)數(shù)據(jù)庫(kù)失敗
IDBOpenDBRequest.onerror = function(e) {
  console.log(e.currentTarget.error.message);
};

// 第一次打開(kāi)成功后或者版本有變化自動(dòng)執(zhí)行以下事件:一般用于初始化數(shù)據(jù)庫(kù)。
IDBOpenDBRequest.onupgradeneeded = function(e) {
  db = e.target.result; // 獲取到 demoDB對(duì)應(yīng)的 IDBDatabase實(shí)例,也就是我們的數(shù)據(jù)庫(kù)。

  if (!db.objectStoreNames.contains(personStore)) {
    //如果表格不存在,創(chuàng)建一個(gè)新的表格(keyPath,主鍵 ; autoIncrement,是否自增),會(huì)返回一個(gè)對(duì)象(objectStore)
    // objectStore就相當(dāng)于數(shù)據(jù)庫(kù)中的一張表。IDBObjectStore類型。
    var objectStore = db.createObjectStore(personStore, {
      keyPath: 'id',
      autoIncrement: true
    });

    //指定可以被索引的字段,unique字段是否唯一。類型: IDBIndex
    objectStore.createIndex('name', 'name', {
      unique: true
    });
    objectStore.createIndex('phone', 'phone', {
      unique: false
    });
  }
  console.log('數(shù)據(jù)庫(kù)版本更改為: ' + dbVersion);
};
  • 數(shù)據(jù)庫(kù)的 objectStore 添加

indexedDB 的增刪改查的操作需要放到一個(gè)事務(wù)中進(jìn)行(推薦)

// 創(chuàng)建一個(gè)事務(wù),類型:IDBTransaction,文檔地址: https://developer.mozilla.org/en-US/docs/Web/API/IDBTransaction
var transaction = db.transaction(personStore, 'readwrite');

// 通過(guò)事務(wù)來(lái)獲取IDBObjectStore
var store = transaction.objectStore(personStore);

// 往store表中添加數(shù)據(jù)
var addPersonRequest = store.add({
 name: '老馬',
 phone: '189111833',
 address: 'aicoder.com'
});

// 監(jiān)聽(tīng)添加成功事件
addPersonRequest.onsuccess = function(e) {
 console.log(e.target.result); // 打印添加成功數(shù)據(jù)的 主鍵(id)
};

// 監(jiān)聽(tīng)失敗事件
addPersonRequest.onerror = function(e) {
 console.log(e.target.error);
};
  • 數(shù)據(jù)庫(kù)的 objectStore 修改
// 創(chuàng)建一個(gè)事務(wù),類型:IDBTransaction,文檔地址: https://developer.mozilla.org/en-US/docs/Web/API/IDBTransaction
var transaction = db.transaction(personStore, 'readwrite');

// 通過(guò)事務(wù)來(lái)獲取IDBObjectStore
var store = transaction.objectStore(personStore);
var person = {
 id: 6,
 name: 'lama',
 phone: '515154084',
 address: 'aicoder.com'
};

// 修改或者添加數(shù)據(jù)。 第一參數(shù)是要修改的數(shù)據(jù),第二個(gè)參數(shù)是主鍵(可省略)
var updatePersonRequest = store.get(6);

// 監(jiān)聽(tīng)添加成功事件
updatePersonRequest.onsuccess = function(e) {
 // var p = e.target.result;  // 要修改的原對(duì)象
 store.put(person);
};

// 監(jiān)聽(tīng)失敗事件
updatePersonRequest.onerror = function(e) {
 console.log(e.target.error);
};
  • 數(shù)據(jù)庫(kù)的 objectStore 刪除
// 創(chuàng)建一個(gè)事務(wù),類型:IDBTransaction,文檔地址: https://developer.mozilla.org/en-US/docs/Web/API/IDBTransaction
var transaction = db.transaction(personStore, 'readwrite');

// 通過(guò)事務(wù)來(lái)獲取IDBObjectStore
var store = transaction.objectStore(personStore);
store.delete(6).onsuccess = function(e) {
 console.log(刪除成功!)
};
  • 根據(jù) id 獲取數(shù)據(jù)
// 創(chuàng)建一個(gè)事務(wù),類型:IDBTransaction,文檔地址: https://developer.mozilla.org/en-US/docs/Web/API/IDBTransaction
var transaction = db.transaction(personStore, 'readwrite');

// 通過(guò)事務(wù)來(lái)獲取IDBObjectStore
var store = transaction.objectStore(personStore);
store.get(6).onsuccess = function(e) {
  console.log(刪除成功!)
};
  • 數(shù)據(jù)庫(kù)的 objectStore 游標(biāo)查詢
var trans = db.transaction(personStore, 'readwrite');
var store = trans.objectStore(personStore);
var cursorRequest = store.openCursor();
cursorRequest.onsuccess = function(e) {
  var cursor = e.target.result;
  if (cursor) {
    var html = template('tbTmpl', cursor.value);
    document.getElementById('tbd').innerHTML += html;
    cursor.continue(); // 游標(biāo)繼續(xù)往下 搜索,重復(fù)觸發(fā) onsuccess方法,如果到最后返回null
  }
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 人生不過(guò)兩件事:生存與生活。 生存的第一要義就是吃飯,所以人間必然少不了煙火氣。當(dāng)炊煙裊裊升起,廚房飄來(lái)飯菜的香氣...
    xyhoney閱讀 285評(píng)論 0 1
  • 簡(jiǎn)悅直播教練恬源閱讀 197評(píng)論 0 2
  • 日月,和五千年前一樣 溫度,形狀,光澤 一層透明的暮靄,罩住 現(xiàn)代詩(shī)意的心臟 時(shí)古時(shí)今,徘徊于兩片海洋 一片是萬(wàn)年...
    Lilylike閱讀 150評(píng)論 0 3
  • 前幾天,毛概老師問(wèn)我們都有什么夢(mèng)想,并且讓我們寫(xiě)到紙上交上去,她當(dāng)場(chǎng)讀出來(lái)了,并且對(duì)那些“不靠譜”的夢(mèng)想進(jìn)行了一番...
    道er閱讀 289評(píng)論 0 0
  • 一大早到達(dá)醫(yī)院,咨詢了之前的主治醫(yī)生,分析了縣城市區(qū)的人流術(shù)和深圳廣州的人流術(shù)之間的利弊: 目前縣城的人流主要是先...
    玲玲A閱讀 283評(píng)論 0 1

友情鏈接更多精彩內(nèi)容