indexedDB 前端數據庫(使用的簡單案例)


前端存儲 之 indexDB

1、indexedDB是什么?
  • indexedDB是一個非關系型數據庫

  • 它不需要我們去寫一些特定的SQL語句來對數據庫進行操作

  • 它是NoSQL的,數據形式使用的json

2、indexedDB出現的意義?
  • 前端存儲,已經有了LocalStorage 和 Cookies ,但是它們都是比較簡單的技術。

  • 而indexedDB提供了 類似數據庫風格的數據儲存 和 使用方式

  • Cookies只能是字符串,儲存空間有限,每次HTTP接受和發送都會傳遞Cookies數據,它會占用額外的流量

  • LocalStorage是用key-value 鍵值模式儲存數據,想讓localstorage存儲對象,你需要借助JSON.stringify() 能將對象變成字符串形式,再用JSON.parse() 將字符串還原成對象,當存儲的數據龐大時,這就不是最佳的方案了,localstorage就是專門為小數量數據設計的,它的api設計為同步的

  • indexedDB很適合存儲大量數據,它的API是異步調用的,indexedDB使用索引存儲數據,各種數據庫操作放在事務中執行,indexedDB支持簡單的數據類型,它比localstorage強大,API也相對復雜,對於簡單的數據,還是使用localstorage。

  • indexedDB能提供更為復雜的查詢數據的方式

3、indexedDB的特性
  • 對象倉庫(objectStore)

    • indexedDB沒有表的概念,而是使用objectStore。

    • 一個數據庫中可以包含多個objectStore

    • objectStore是一個靈活的數據結構,可以存放多種類型數據,也就是說一個objectStore相當於一張表,里面儲存的每條數據和一個鍵相關。

    • 我們可以使用每條記錄中的某個字段作為鍵值(keyPath),也可以使用自動生成的遞增數字作為鍵值(keyGenerator),也可以不指定。

    • 選擇鍵的類型不同,objectStore可以存儲的數據結構也有差異

  • 事務性

    • 在indexedDB中,每一個對數據庫操作是在一個事務的上下文中執行的。

    • 事務范圍一次影響一個或多個objectstores。

    • 你通過傳入一個objectstores名字的數組到創建事務 范圍的函數來定義

      • 比如: db.transaction( storeName, ' readwrite' ),創建事務的第二個參數是事務模式,當請求一個事務時,必須決定是按照只讀還是讀寫模式模式請求訪問

  • 基於請求

    • 對indexedDB數據庫的每次操作,描述為通過一個請求打開數據庫,訪問一個object store,再繼續。

    • indexedDB API天生是基於請求的,這也是API異步本性指示,對於你在數據庫執行的每次操作,你必須首先為這個操作創建一個請求,當請求完成,你可以響應由請求結果產生的事件和錯誤

  • 異步

    • 在indexedDB 大部分操作並不是我們常用的調用方法,返回結果的模式,而是請求 ----> 響應的模式

    • 所謂異步API是指並不是這條指令執行完畢,我們就可以使用 request.result 來獲取 indexedDB 對象了。

    • 類似於 我們使用ajax一樣,語句執行完並不代表已經獲取到了對象,所以我們一般在其回調函數中處理。

4、玩 indexedDB 的基本步驟

  1. 打開數據庫並且開始一個事務

  2. 創建一個 object store

  3. 構建一個請求執行一些數據庫操作,比如新增或者提取數據等

  4. 通過監聽正確類型的DOM事件可以等待操作完成

  5. 在操作結果上進行一些操作(可以在 request 對象中找到)

代碼案例:

1、打開數據庫,需要當前瀏覽器支持indexedDB

var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
​
if( !indexedDB ){
    alert('當前不支持 indexedDB 數據庫');
    throw Error('當前不支持 indexed 數據庫');
}

2、創建數據庫

function createDB(dbName, version) {
    // 參數為:數據庫名和版本號
    // 數據庫存在則打開,否則創建
    let request = indexedDB.open(dbName, version);
    /**
     * request 並不會返回一個DB對象的句柄,我們得到的是一個IDBOpenDBRequest對象
     * 而我們期望得到的DB對象在其result屬性中
     * 除了 result,IDBOpenDBRequest 接口定義了幾個重要屬性
     * onerror:請求失敗的回調函數句柄
     * onsuccess:請求成功的回調函數句柄
     * onupgradeneeded:請求數據庫版本變化句柄
     * 第一次打開數據庫,會先觸發 onupgradeneeded 事件,然后觸發success事件。
     */
    console.log(request);
​
    // 請求數據庫失敗的回調函數
    request.onerror = function(err) {
        console.log(JSON.stringify(err));
        console.log('打開數據庫失敗,錯誤信息為:' + err.target.message);
    }
​
    // 請求數據庫成功的回調函數
    request.onsuccess = function(success) {
        console.log(JSON.stringify(success));
        console.log('打開數據庫成功:' + success.target.result);
​
        /**
         *  獲取數據庫實例對象,
         *  db.createObjectStore('table6',{keyPath:'stuId',autoIncrement:true});
         *  var len = db.objectStoreNames.length; --> 對象儲存空間名的個數
         *  var name = db.objectStoreNames[1]; --> 對象存儲空間名
         *  transaction = db.transaction(['table'],'readwrite'); --> 事務操作的對象存儲空間名,事務模式:'readwrite'可讀寫模式
         * 
         *  // 向info儲存空間加入一個info對象,獲得request對象用於處理用戶對數據庫的操作請求
         *  // 同樣擁有 onerror 、onupgradeneeded 、onsuccess 事件
         *  objectStore = transaction.objectStore('table');
         */
        let db = success.target.result;
    }
​
    // 數據庫版本更新
    request.inuparadeneeded = function(event) {
        console.log(JSON.stringify(event));
        console.log('數據庫版本有變化...');
​
        let db = event.target.result;
​
        // 判斷對象儲存空間名稱是否存在
        if (!db.objectStoreNames.contains('table')) {
​
​
            //創建信息對象存儲空間;指定keyPath選項為Id(即主鍵為Id)
            let objectStore = db.createObjectStore('table', {
                keyPath: 'stuId',
                autoIncrement: true
            });
            /*
             *db.createObjectStore("table1", {keyPath: "userId",autoIncrement: true});
             *db.createObjectStore("table2", {keyPath: "userId",autoIncrement: true});
             *db.createObjectStore("table3", {keyPath: "userId",autoIncrement: true});
             *db.createObjectStore("table4", {keyPath: "userId",autoIncrement: true});
             *當然了。你可以一次性的在這里建立多個對象空間 或者每次改變 version和對象空間的名字。之前創建的會存在。
             * 為什么在onupgradeneeded中創建呢?
             * 原因:當dbName和 version 這兩個參數中的任何一個發生變化。都會執行重新創建一遍對象空間,
             * 注意:當dbName,保持不變,version 只能逐漸增加,假如你這次 version = 3.那么下次 version = 2.就會報錯 打開數據庫失敗:
             * version!=0;
             * */
​
​
            // 創建索引
            // 索引名,創建索引的列,索引選項(索引屬性值是否唯一:true or false)
            // 注意: 創建索引 要在創建對象空間的時候
            // unique:true 實際效果:這個索引的內容是唯一的,不能重復,無法創建兩個(索引屬性值)相同的內容
            objectStore.createIndex('studentIndex', 'stuId', {
                unique: true
            });
        }
    }
​
}

3、刪除數據庫 or 關閉數據庫

// 關閉與刪除數據庫
function deleteDB(dbName) {
​
    try {
        // 刪除數據庫使用 indexedDB對象的deleteDatabase方法
        let request = indexedDB.deleteDatabase(dbName);
​
        request.onerror = function() {
            console.log('刪除[' + dbName + ']數據庫失敗!!!!');
        }
​
        request.onsuccess = function() {
            console.log('刪除[' + dbName + ']數據庫成功!!!!');
        }
​
    } catch (e) {
        console.log('刪除[' + dbName + ']數據庫出現錯誤,' + e.getMessage);
    }
}
​
// 關閉數據庫
function colseDB(dbName){
    dbName.close();
}

4、新增數據

// 新增數據
// 數據庫名稱,對象倉庫(表名),傳入的參數
function insert(dbName, objectStoreName, argument) {
    // 打開數據庫
    let request = indexedDB.open(dbName);
    // 請求數據庫成功的回調函數
    request.onsuccess = function(success) {
        // 獲取數據庫實例對象
        let db = success.target.result;
        // 對某個表 進行事務操作的事務權限控制 
        let transaction = db.transaction(objectStoreName, 'readwrite');
        // 對表進行操作
        let objectStore = transaction.objectStore(objectStoreName);
​
        // 使用add方法,此方法是異步的
        // 有success,error事件
        //objectStore.add(argument);
        // 使用定義add方法
        let add = objectStore.add(argument);
        
        let msg = JSON.stringify(argument);
        
        // 添加成功的回調函數
        add.onsuccess = function(e) {
            console.log(e);
            console.log('向表[' + objectStoreName + ']新增一條數據為[' + msg + ']成功!!');
        }
        add.error = function(e) {
            console.log('向表[' + objectStoreName + ']新增一條數據為[' + msg + ']失敗!!');
        }
    }
​
}
​
var stu1 = {
    name: '歐可樂',
    age: 19,
    sex: '男'
};
​
 insert('studentDB','student',stu1);
​

5、查詢數據

// 查詢數據
// 數據庫名,對象倉庫(表名),查詢參數(鍵名對應的值)
function getData(dbName, objectStoreName, selectArgument){
    // 打開數據庫
    let request = indexedDB.open(dbName);
    // 請求打開數據庫的回調函數
    request.onsuccess = function(success){
        let db = success.target.result;
        let transaction = db.transaction([objectStoreName],'readwrite');
        let objectStore = transaction.objectStore(objectStoreName);
        let getResult = objectStore.get(selectArgument);
​
        getResult.onsuccess = function(e){
            console.log( e.target.result);
        }
​
    }
​
}
​
getData('studentDB','student',1);

6、更新數據

// 更新數據
// 數據庫名,表名,要更新數據的標志(id),新的數據
function update(dbName, objectStoreName, id, newsData) {
    // 打開數據庫
    let request = indexedDB.open(dbName);
    // 請求打開數據庫的回調函數
    request.onsuccess = function(success) {
        // 獲取到數據庫的表
        let db = success.target.result;
        // 對表操作進行事務權限控制
        let transaction = db.transaction(objectStoreName, 'readwrite');
        // 對表進行操作
        let objectStore = transaction.objectStore(objectStoreName);
        // 根據鍵值 獲取某個實例中的某條數據
        let getResult = objectStore.get(id);
        // 實例成功的回調函數
        getResult.onsuccess = function(e) {
            // 源數據
            let msg = e.target.result;
            let old = JSON.stringify(msg);
            // 重新賦值
            msg.name = newsData.name;
            msg.age = newsData.age;
            msg.sex = newsData.sex;
            objectStore.put(msg);
            console.log('更新主鍵為 stuId:' + msg.stuId + '的數據,原數據:[' + old + '],新數據為:[' + JSON.stringify(e.target.result) +
                        '],更新成功!!!');
        }
        // 實例失敗的回調函數
        getResult.onerror = function(e) {
            console.log('數據更新失敗!!');
        }
    }
}
​
let stu2 = {
    name: '小可樂',
    age: 18,
    sex: '男'
}
update('studentDB', 'student', 1, stu2);

7、刪除數據

// 刪除數據
// 數據庫名,表名,主鍵
function deleteData(dbName, tableName, id){
    // 打開數據庫
    let request = indexedDB.open(dbName);
    // 請求打開數據庫成功的回調函數
    request.onsuccess = function(success){
        // 獲取實例
        let db = success.target.result;
        // 事務權限控制
        let transaction = db.transaction(tableName, 'readwrite');
        // 進行操作
        let objectStore = transaction.objectStore(tableName);
        // 進行刪除
        let deleteMsg = objectStore.delete(id);
        deleteMsg.onsuccess = function(e){
            console.log('成功刪除主鍵stuId為:' + id+',的數據,狀態為:'+e.isTrusted);
        }
    }
}
​
deleteData('studentDB','student',1);

8、清除表數據

// 清空表數據
// 數據庫名稱,表名
function clearData(dbName, tableName) {
    // 請求打開數據庫
    let request = indexedDB.open(dbName);
    // 請求成功的回調函數
    request.onsuccess = function(e) {
        // 獲取實例
        let db = e.target.result;
        // 表名事務權限控制
        let transaction = db.transaction(tableName, 'readwrite');
        // 進行操作
        let objectStore = transaction.objectStore(tableName);
        // 清除數據
        let clearResult = objectStore.clear();
        // 清除成功的回調函數
        clearResult.onsuccess = function(e) {
            console.log('表名[' + tableName + ']數據清除成功,狀態為:' + e.isTrusted );
        }
    }
}
clearData('studentDB', 'student');

9、使用索引查詢

// 利用索引查詢
// 數據庫,表名,索引名, 查詢的值
function searchIndex(dbName, tableName, indexName, indexValue) {
    // 請求打開數據
    let request = indexedDB.open(dbName);
    // 請求打開數據庫成功的回調函數
    request.onsuccess = function(e) {
        // 獲取到實例
        let db = e.target.result;
        // 賦予事務權限
        let transaction = db.transaction(tableName, 'readwrite');
        // 基於權限進行操作
        let objectStore = transaction.objectStore(tableName);
        // 索引
        let index = objectStore.index(indexName);
        // 獲取結果
        let result = index.get(indexValue);
        // 結果獲取成功的回調函數
        result.onsuccess = function(e) {
            console.log('索引名:' + indexName + ',索引值:' + indexValue + ',查詢的結果:[' + JSON.stringify( e.target.result ) + ']');
        }
    }
}
searchIndex('studentDB','student','studentIndex',2);

10、使用游標讀取全部的數據

// 使用 游標
// 數據庫名稱,表名
function readAll(dbName, tableName) {
    // 請求打開數據庫
    let request = indexedDB.open(dbName);
    // 請求成功的回調函數
    request.onsuccess = function(e) {
        // db = e.target.result // 獲取實例
        // transaction = db.transaction(tableName,'readwrite'); // 權限控制
        // objectStore = transaction.objectStore(tableName); // 進行操作對象
        let objectStore = e.target.result.transaction(tableName, 'readwrite').objectStore(tableName);
        // 打開游標
        let cursor = objectStore.openCursor();
​
        // 儲存值
        let arr = [];
​
        // 成功打開游標的回調函數
        cursor.onsuccess = function(e) {
            let result = e.target.result;
​
            if (result) {
                // 將數據一條一條保存到arr中
                arr.push(result.value);
                result.continue();
            } else {
                if (!arr) {
                    console.log('沒有數據....');
                } else {
                    console.log('[' + tableName + ']表中的數據為:' + JSON.stringify(arr));
                }
            }
        }
    }
}
readAll('studentDB', 'student');


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM