indexedDB入門

devman發表於2019-02-13

概述

IndexedDB 是一個事務型資料庫系統,類似於基於 SQL 的 RDBMS。 然而不同的是它使用固定列表,IndexedDB 是一個基於 JavaScript 的物件導向的資料庫。

現有的瀏覽器資料儲存方案,都不適合儲存大量資料:Cookie 的大小不超過 4KB,且每次請求都會傳送回伺服器 LocalStorage 在 2.5MB 到 10MB 之間(各家瀏覽器不同),而且不提供搜尋功能,不能建立自定義的索引。所以,需要一種新的解決方案,這就是 IndexedDB 誕生的背景

簡單來說,IndexedDB 就是瀏覽器提供的本地資料庫。

IndexedDB 具有以下特點

  • 鍵值對儲存
  • 非同步操作(避免鎖死瀏覽器)
  • 支援事務
  • 同源限制(協議+域名+埠)
  • 儲存空間大
  • 支援二進位制儲存(ArrayBuffer 物件和 Blob 物件,可儲存檔案資料)

基本概念

對比關聯式資料庫 MySql 可以得到以下關係

  • 資料庫:IDBDatabase
  • 表格:物件倉庫(IDBObjectStore)
  • 行資料:物件倉庫儲存的一條資料
  • 索引:IDBindex,加速資料的檢索(在物件倉庫裡面可為不同的鍵建立)
  • 事務:IDBTransaction
  • 操作請求:IDBRequest
  • IDBCursor:遍歷物件儲存空間和索引
  • IDBKeyRange:定義鍵的範圍資料

基本操作

相容性注意點

// 全域性變數相容性問題

window.indexedDB =
    window.indexedDB ||
    window.mozIndexedDB ||
    window.webkitIndexedDB ||
    window.msIndexedDB;

window.IDBTransaction =
    window.IDBTransaction ||
    window.webkitIDBTransaction ||
    window.msIDBTransaction;

window.IDBKeyRange =
    window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;

if (!window.indexedDB) {
    window.alert(
        "Your browser doesn't support a stable version of IndexedDB. Such and such feature will not be available."
    );
}
複製程式碼

資料庫操作

開啟/新建資料庫

var databaseName = "MyTestDatabase";
var databaseVersion = 1;

// 開啟資料庫
var request = window.indexedDB.open(databaseName, databaseVersion);

request.onsuccess = function(event) {
    console.log("open success");
};

request.onerror = function(event) {
    console.log("open fail");
};

request.onupgradeneeded = function(event) {};
複製程式碼

window.indexedDB.open函式開啟對應的資料庫,如果沒有該資料庫就會新建。

新建資料庫或者資料庫版本大於當前版本會觸發onupgradeneeded事件

資料庫為什麼會有版本? 因為資料庫的資料解構可能會發生改變的,所以一般修改資料解構的操作在onupgradeneeded裡面書寫

刪除資料庫

window.indexedDB.deleteDatabase(databaseName);
複製程式碼

物件倉庫操作(表格操作)

建立和修改表格是修改資料庫的資料解構,所以我把他們寫在onupgradeneeded事件裡

建立表格

request.onupgradeneeded = function(event) {
    console.log("onupgradeneeded");
    db = event.target.result;

    // 建立倉庫物件(建立表格)
    // 這裡我將主鍵設定為id
    var objectStore = db.createObjectStore(objectStoreName, {
        keyPath: "id",
        autoIncrement: true
    });
};
複製程式碼

刪除表格

request.onupgradeneeded = function(event) {
    console.log("onupgradeneeded");
    db = event.target.result;

    // 刪除倉庫物件(刪除表格)
    db.deleteObjectStore(objectStoreName);
};
複製程式碼

資料操作(行資料操作)

新增資料(增)

var databaseName = "MyTestDatabase";
var databaseVersion = 1;
var db;
var objectStoreName = "objectStore1";
var storeDatas = [
    { id: "1", name: "張三", age: 18 },
    { id: "2", name: "李四", age: 19 }
];

var request = window.indexedDB.open(databaseName, databaseVersion);

request.onsuccess = function(event) {
    console.log("open success");
    db = event.target.result;

    // 將資料儲存到新建的物件倉庫
    var objectStore = db
        .transaction([objectStoreName], "readwrite")
        .objectStore(objectStoreName);

    storeDatas.forEach(function(dataItem) {
        // 新增一條資料
        objectStore.add(dataItem);
    });
};
複製程式碼

刪除資料(刪)

var databaseName = "MyTestDatabase";
var databaseVersion = 1;
var db;
var objectStoreName = "objectStore1";
var storeDatas = [
    { id: "1", name: "張三", age: 18 },
    { id: "2", name: "李四", age: 19 }
];

var request = window.indexedDB.open(databaseName, databaseVersion);

request.onsuccess = function(event) {
    console.log("open success");
    db = event.target.result;

    console.log("刪除資料");
    var req = db
        .transaction([objectStoreName], "readwrite")
        .objectStore(objectStoreName)
        .delete("2"); // 這裡的“2”指定的是主鍵的鍵值

    req.onsuccess = function() {
        console.log("刪除成功");
    };

    req.onerror = function() {
        console.log("刪除失敗");
    };
};
複製程式碼

修改資料(改)

console.log("更新資料");
var req = db
    .transaction([objectStoreName], "readwrite")
    .objectStore(objectStoreName)
    .put({
        id: "2",
        name: "王五",
        age: 17
    }); // 將整條資料給替換

req.onsuccess = function() {
    console.log("更新成功");
};

req.onerror = function() {
    console.log("更新失敗");
};
複製程式碼

獲取資料(查)

console.log("讀取資料");
var req = db
    .transaction([objectStoreName], "readonly")
    .objectStore(objectStoreName)
    .get("1"); // 這裡的“1”也是主鍵的鍵值

req.onsuccess = function() {
    console.log("獲取成功");
    console.log(req.result);
};

req.onerror = function() {
    console.log("獲取失敗");
};
複製程式碼

通過指標物件遍歷表格資料

console.log("遍歷資料");
var objectStore = db
    .transaction([objectStoreName], "readonly")
    .objectStore(objectStoreName);

var count = 0;
objectStore.openCursor().onsuccess = function(event) {
    var cursor = event.target.result;
    if (cursor) {
        console.log(`第${++count}條資料為`);
        console.log(cursor.value);
        cursor.continue(); // 將指標移動下一個位置
    } else {
        console.log("沒有更多資料");
    }
};
複製程式碼

小結

indexedDB的API還是非常多的,這裡只是簡單介紹了最常用的幾個操作(個人認為^_^)。

參考文件

相關文章