本地數據存儲之 IndexedDB 實踐

本地存儲的類型

本地存儲主要有如下幾種:數據庫

  • Web Sql
  • IndexedDB
  • Local Storage
  • Session Storage
  • Cookies
  • Application Cache

項目需求

  • 離線存儲讀取數據
  • 容許用戶對數據進行增刪改操做
  • 數據存儲在本地,不依賴後端
  • 數據支持索引查詢

因爲 WebSQL 在標準上還存在爭議,而 localStorage 實現數據分頁、查詢比較複雜,最終考慮使用了 IndexedDB 來知足需求。後端

IndexedDB 支持狀況

圖片描述

IndexedDB 數據庫的使用

定義數據庫對象

var wxbDB = {
    name   : "wxb",
    version: 1,
    db     : null
};

此處咱們定義了一個數據庫對象,包括name 數據庫名稱,version 數據庫的版本,以及 db 數據對象。數據結構

數據庫初始化

function initDB(dbObj) {
    dbObj.version = dbObj.version || 1;
    var request = indexedDB.open(dbObj.name, dbObj.version);
    request.onerror = function (e) {
        console.log(e.currentTarget.error.message);
    };
    request.onsuccess = function (e) {
        dbObj.db = e.target.result;
    };
    request.onupgradeneeded = function (e) {
        var thisDB = e.target.result;
        if (!thisDB.objectStoreNames.contains("material")) {
            var objStore = thisDB.createObjectStore("material", {keyPath: "id", autoIncrement: true});
            objStore.createIndex("wxid", "wxid", {unique: true});
        }
        if (!thisDB.objectStoreNames.contains("account")) {
            var objStore = thisDB.createObjectStore("account", {keyPath: "id", autoIncrement: true});
            objStore.createIndex("wxid", "wxid", {unique: true});
            objStore.createIndex("nickName", "nickName", {unique: false});
        }
    };
}

indexedDB.open 方法能夠建立或者打開一個 IndexedDB,並返回 IDBOpenDBRequest 對象。併發

IDBOpenDBRequest 對象除了onerroronsuccess,還有一個相似回調函數句柄 onupgradeneeded。這個句柄在咱們請求打開的數據庫的版本號和已經存在的數據庫版本號不一致的時候調用。函數

indexedDB.open 方法的第二個可選參數是數據庫版本號,數據庫建立的時候默認版本號爲 1,當咱們傳入的版本號和數據庫當前版本號不一致時 onupgradeneeded 就會被調用,固然咱們不能試圖打開比當前數據庫版本低的version,不然調用的就是 onerror 了。this

onupgradeneeded 被調用時,咱們能夠作一些建表、索引等操做。spa

有了數據庫後咱們天然但願建立一個表用來存儲數據,但 indexedDB 中沒有表的概念,而是 objectStore,一個數據庫中能夠包含多個 objectStoreobjectStore 是一個靈活的數據結構,能夠存放多種類型數據。code

咱們可使用每條記錄中的某個指定字段做爲鍵值(keyPath),也可使用自動生成的遞增數字做爲鍵值(keyGenerator),也能夠不指定。選擇鍵的類型不一樣,objectStore 能夠存儲的數據結構也有差別。對象

  • 不使用 :任意值,可是沒添加一條數據的時候須要指定鍵參數
  • keyPath : Javascript 對象,對象必須有一屬性做爲鍵值
  • keyGenerator : 任意值
  • 都使用 : Javascript 對象,若是對象中有 keyPath 指定的屬性則不生成新的鍵值,若是沒有自動生成遞增鍵值,填充 keyPath 指定屬性

圖片描述

關閉數據庫

function closeDB(dbObj) {
    dbObj.db.close();
}

刪除數據庫

function deleteDB(dbObj) {
    indexedDB.deleteDatabase(dbObj.name);
}

數據庫表的 CURD

在對新數據庫作任何事情以前,須要開始一個事務。事務中須要指定該事務跨越哪些 object storeblog

事務具備三種模式

  • 只讀:read,不能修改數據庫數據,能夠併發執行
  • 讀寫:readwrite,能夠進行讀寫操做
  • 版本變動:verionchange

  • 添加數據

    function addData(dbObj, tableName, data, cb) {
        var transaction = dbObj.db.transaction(tableName, 'readwrite');
        transaction.oncomplete = function () {
            console.log("transaction complete");
        };
        transaction.onerror = function (event) {
            console.dir(event)
        };
    
        var objectStore = transaction.objectStore(tableName);
        var request = objectStore.add(data);
        request.onsuccess = function (e) {
            if (cb) {
                cb({
                    error: 0,
                    data : data
                })
            }
        };
        request.onerror = function (e) {
            if (cb) {
                cb({
                    error: 1
                })
            }
        }
    }

插入數據

讀取數據

  • 刪除數據

    function deleteData(dbObj, tableName, id, cb) {
        var transaction = dbObj.db.transaction(tableName, 'readwrite');
        transaction.oncomplete = function () {
            console.log("transaction complete");
        };
        transaction.onerror = function (event) {
            console.dir(event)
        };
        var objectStore = transaction.objectStore(tableName);
        var request = objectStore.delete(parseInt(id));
        request.onsuccess = function (e) {
            if (cb) {
                cb({
                    error: 0,
                    data : parseInt(id)
                })
            }
        };
        request.onerror = function (e) {
            if (cb) {
                cb({
                    error: 1
                })
            }
        }
    }
  • 查詢數據

    1. 獲取所有數據
      function getDataAll(dbObj, tableName, cb) {
          var transaction = dbObj.db.transaction(tableName, 'readonly');
          transaction.oncomplete = function () {
              console.log("transaction complete");
          };
          transaction.onerror = function (event) {
              console.dir(event)
          };
      
          var objectStore = transaction.objectStore(tableName);
          var rowData = [];
          objectStore.openCursor(IDBKeyRange.lowerBound(0)).onsuccess = function (event) {
              var cursor = event.target.result;
              if (!cursor && cb) {
                  cb({
                      error: 0,
                      data : rowData
                  });
                  return;
              }
              rowData.push(cursor.value);
              cursor.continue();
          };
      }

      圖片描述

    2. 根據 id 獲取數據

      function getDataById(dbObj, tableName, id, cb) {
          var transaction = dbObj.db.transaction(tableName, 'readwrite');
          transaction.oncomplete = function () {
              console.log("transaction complete");
          };
          transaction.onerror = function (event) {
              console.dir(event)
          };
      
          var objectStore = transaction.objectStore(tableName);
          var request = objectStore.get(id);
          request.onsuccess = function (e) {
              if (cb) {
                  cb({
                      error: 0,
                      data : e.target.result
                  })
              }
          };
          request.onerror = function (e) {
              if (cb) {
                  cb({
                      error: 1
                  })
              }
          }
      }
    3. 根據關鍵詞索引獲取數據

      function getDataBySearch(dbObj, tableName, keywords, cb) {
          var transaction = dbObj.db.transaction(tableName, 'readwrite');
          transaction.oncomplete = function () {
              console.log("transaction complete");
          };
          transaction.onerror = function (event) {
              console.dir(event)
          };
      
          var objectStore = transaction.objectStore(tableName);
          var boundKeyRange = IDBKeyRange.only(keywords);
          var rowData;
          objectStore.index("nickName").openCursor(boundKeyRange).onsuccess = function (event) {
              var cursor = event.target.result;
              if (!cursor) {
                  if (cb) {
                      cb({
                          error: 0,
                          data : rowData
                      })
                  }
                  return;
              }
              rowData = cursor.value;
              cursor.continue();
          };
      }
    4. 根據頁碼獲取數據

      function getDataByPager(dbObj, tableName, start, end, cb) {
          var transaction = dbObj.db.transaction(tableName, 'readwrite');
          transaction.oncomplete = function () {
              console.log("transaction complete");
          };
          transaction.onerror = function (event) {
              console.dir(event)
          };
      
          var objectStore = transaction.objectStore(tableName);
          var boundKeyRange = IDBKeyRange.bound(start, end, false, true);
          var rowData = [];
          objectStore.openCursor(boundKeyRange).onsuccess = function (event) {
              var cursor = event.target.result;
              if (!cursor && cb) {
                  cb({
                      error: 0,
                      data : rowData
                  });
                  return;
              }
              rowData.push(cursor.value);
              cursor.continue();
          };
      }
  • 更新數據

    function updateData(dbObj, tableName, id, updateData, cb) {
        var transaction = dbObj.db.transaction(tableName, 'readwrite');
        transaction.oncomplete = function () {
            console.log("transaction complete");
        };
        transaction.onerror = function (event) {
            console.dir(event)
        };
    
        var objectStore = transaction.objectStore(tableName);
        var request = objectStore.get(id);
        request.onsuccess = function (e) {
            var thisDB = e.target.result;
            for (key in updateData) {
                thisDB[key] = updateData[key];
            }
            objectStore.put(thisDB);
            if (cb) {
                cb({
                    error: 0,
                    data : thisDB
                })
            }
        };
        request.onerror = function (e) {
            if (cb) {
                cb({
                    error: 1
                })
            }
        }
    }

ps: 實現細節部分待有時間進行補充完善~

相關文章
相關標籤/搜索