indexedDB使用指南

基本概念

IndexedDB是一種在瀏覽器中持久存儲數(shù)據(jù)的方法,允許我們不考慮網(wǎng)絡(luò)可用性,創(chuàng)建具有豐富查詢能力的可離線web應(yīng)用程序。indexedDB對于存儲大量數(shù)據(jù)的應(yīng)用程序和不需要持久internet鏈接的應(yīng)用程序(例如郵件客戶端、待辦事項(xiàng)列或記事本)很有用

幾條重要的概念(需熟知)

  1. 首先IndexedDB是一個(gè)key-value型數(shù)據(jù)庫,可以使用一個(gè)key作為索引獲取或者存儲數(shù)據(jù)

  2. IndexedDB是事務(wù)模式的數(shù)據(jù)庫。

  3. 其次IndexedDB是一種異步API

  4. IndexedDB是面向?qū)ο蟮?。要求我們?yōu)橐环N數(shù)據(jù)創(chuàng)建一個(gè)對象倉庫(objectStore),只要這種數(shù)據(jù)是一個(gè)js對象即可。

5 . IndexedDB支持同源策略。

基本模式

IndexedDB 鼓勵(lì)使用的基本模式如下所示:

  1. 打開數(shù)據(jù)庫
  2. 在數(shù)據(jù)庫中創(chuàng)建一個(gè)對象倉庫(object store)
  3. 啟動一個(gè)事務(wù),并發(fā)送一個(gè)請求來執(zhí)行數(shù)據(jù)庫操作,如增加或提取數(shù)據(jù)等
  4. 通過監(jiān)聽正確類型的dom事件以等待操作完成
  5. 在操作結(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)。鍵的提供有以下幾種不同方法:


image.png
// 我們的客戶數(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)行操作。

  1. versionchange: 如果想要修改數(shù)據(jù)庫模型或者接口,包括新建或者刪除對象倉庫或者索引,只能在versionchange事務(wù)中才能實(shí)現(xiàn)。
  2. readonly: 只讀
  3. 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)試

image.png

可以在圖中application-->indexedDB中進(jìn)行查看。

indexedDB與localstorage的區(qū)別

IndexedDB 的儲存空間比 LocalStorage 大得多,一般來說不少于 250MB,甚至沒有上限。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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