HTML5-indexedDB使用總結

1. 特點

IndexedDB 是一種可以讓你在用戶的瀏覽器內持久化存儲數據的方法。特點如下:
* 支持事務、遊標、索引等數據庫操作
* 一般瀏覽器會分配50M-250M不等的內存
* 持久化存儲,清除瀏覽器緩存不會被刪除(localStorage是會被刪除的)
* 支持多種數據格式:arrayBuffer、String、Object、Array、File、Blob、ImageData都ok
* 不支持跨域,一個域可以有多個數據庫
* 開發中需要謹記的一個特性:異步操作,換句話說,所有操作都需要在回調函數中完成

2. 兼容性

前端在學一項技術時候,往往先關注它的兼容性,再牛的技術,不兼容也是用不到項目中的。

這裏寫圖片描述
這是can i use中指示的情況,我實測的結果是:
* PC端chrome 54上有特殊表現(在第一次打開indexedDB時,upgradeneeded事件不觸發),firfox表現正常
* 移動端ios8-ios10 safari支持,但是X5內核不支持;android上X5內核支持

3. 使用

基本使用模式如下:
1. 打開數據庫
2. 建立一個事務
3. 在事務請求的回調函數中處理事務處理的結果
4. 使用完畢關閉數據庫

3.1 基本概念

數據庫

一個數據庫由數據庫名和其版本兩個屬性

事務

事務用於操縱數據庫中數據,每個事務有不同的模式:readonly、readwrite或者versionchange。簡單說下versionchange,在這個事務中,可以讀取、更新、刪除已經存在的數據,也可以刪除和新建對象存儲空間(object stores)和索引。該類型事務不能手動創建,但是在upgradeneeded事件被觸發時會自動創建。

對象存儲空間

object store,我理解類似數據庫的表。一個數據庫會有多個對象存儲空間,對象存儲空間中存儲着數據。

key

每條數據有一個key,這個key可以是每次存儲時用戶自己具體決定某個值,可以是用戶在新建object store時使用傳入對象的某個字段,也可以讓數據庫自己生成。
這裏寫圖片描述
具體使用如下:

//使用傳入對象的某個字段作爲key
var objectStore = db.createObjectStore("storeName", { keyPath: "proOfObj" });
//使用具體某個字段作爲key
var objectStore = transaction.objectStore("storeName");
//自動生成key
var objectStore = db.createObjectStore("storeName", {autoIncrement: true});

upgradeneeded事件

就是版本號變更觸發的事件。注意,版本號只能增加,不能減少。新建object store的工作必須在這個事件的回調裏寫,至少我測試是必須,如果在打開數據庫的success事件中寫,會報錯。多麼神奇。

3.2 實例代碼

我對你使用indexedDB的提醒就是,記住異步操縱。

class IndexedDB{
    constructor(dbName, storeName, version){
        this.storeName = storeName;
        const indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
        const request = indexedDB.open(dbName, version);

        request.onsuccess = e => {
            this.db = e.target.result;
            console.log('Init indexedDB successfully');
        };
        request.onupgradeneeded = e => {
            this.db = e.target.result;
           if(!this.db.objectStoreNames.contains(storeName)){
                this.store = this.db.createObjectStore(storeName);
            }
            console.log('DB version changed, db version: ', this.db.version);
        };
        request.onerror = e => {console.info('Can not open indexedDB', e);};
    }
    get(key, callback){
        const transaction = this.db.transaction(this.storeName);
        const objectStore = transaction.objectStore(this.storeName);
        const request = objectStore.get(key);

        request.onerror = e => {console.info('Can not get value', e);};
        request.onsuccess = e => {callback(e.target.result);};
    }
    set(value, key){
        let oldValue;
        this.get(key, function(res){oldValue = res;});

        if(oldValue){
            console.info('You should use function update');
        }else{
            const transaction = this.db.transaction(this.storeName, 'readwrite');
            const objectStore = transaction.objectStore(this.storeName);
            const request = objectStore.add(value, key);

            request.onerror = e => {console.info('Can not add value', e);};
        }
    }
    update(newValue, key){
        const oldValue = this.get(key);

        if(!oldValue){
            console.info('You should use function set');
        }else{
            const transaction = this.db.transaction(this.storeName, 'readwrite');
            const objectStore = transaction.objectStore(this.storeName);
            const request = objectStore.put(newValue, key);

            request.onerror = e => {console.info('Can not update value', e);};
        }
    }
    remove(key){
        const request = this.db.transaction(this.storeName, 'readwrite')
                .objectStore(this.storeName)
                .delete(key);
        request.onerror = e => {console.info('Can not remove value', e);};
    }
    close(){
        this.db.close();
    }
}

我這裏對indexedDB的操作做了一個封裝,對get方法異步處理的方式是傳入一個回調,其實也可以使用thunk或者返回一個promise,大家可以自己試試。

參考連接:
https://w3c.github.io/IndexedDB/
https://www.w3.org/TR/IndexedDB/
https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API/Using_IndexedDB

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章