新建 indexedDB 數據庫並插入數據


一、什么叫數據庫

DB的全名是database,即數據庫。

二、數據庫的種類

數據庫有兩種類型,分別是關系型數據庫和非關系型數據庫。

  • 關系型數據庫:OracleDB2MicrosoftSQLServer、MicrosoftAccess、MySQL等。
  • 非關系型數據庫:NoSql、Cloudant、MongoDb、redis、HBase等。

關系型數據庫的優點:

  1. 能夠復雜查詢:可以用SQL句子便捷的在一個表及多個表之間做復雜的數據查詢。
  2. 事務支持性優秀:能夠實現對於安全性要求很高的數據訪問。

非關系型數據庫的優點:

  1. 性能好:NOSQL是基於鍵值對的,可以想象成表中的主鍵和值的對應關系,並且不用通過SQL層的解析,因此性能表現優異。
  2. 可擴展性好:同樣也是基於鍵值對,數據間耦合度低,因此很容易水平擴展。
  • SQL (Structured Query Language) 是一種數據庫語言 。
  • 就數據庫類型而言,IndexedDB 不屬於關系型數據庫(不支持 SQL 查詢語句),更接近 NoSQL 數據庫。

IndexedDB 具有以下特點

(1)鍵值對儲存。 IndexedDB 內部采用對象倉庫(object store)存放數據。所有類型的數據都可以直接存入,包括 JavaScript 對象。對象倉庫中,數據以"鍵值對"的形式保存,每一個數據記錄都有對應的主鍵,主鍵是獨一無二的,不能有重復,否則會拋出一個錯誤。

(2)異步。 IndexedDB 操作時不會鎖死瀏覽器,用戶依然可以進行其他操作,這與 LocalStorage 形成對比,后者的操作是同步的。異步設計是為了防止大量數據的讀寫,拖慢網頁的表現。

(3)支持事務。 IndexedDB 支持事務(transaction),這意味着一系列操作步驟之中,只要有一步失敗,整個事務就都取消,數據庫回滾到事務發生之前的狀態,不存在只改寫一部分數據的情況。

(4)同源限制 IndexedDB 受到同源限制,每一個數據庫對應創建它的域名。網頁只能訪問自身域名下的數據庫,而不能訪問跨域的數據庫。

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

(6)支持二進制儲存。 IndexedDB 不僅可以儲存字符串,還可以儲存二進制數據(ArrayBuffer 對象和 Blob 對象)。

  • 數據庫是一系列相關數據的容器。
  • 每個數據庫包含若干個對象倉庫(object store)。它類似於關系型數據庫的表格。
  • 對象倉庫保存的是數據記錄。每條記錄類似於關系型數據庫的行,但是只有主鍵和數據體兩部分。
  • 數據庫 > 對象倉庫 > 數據記錄

操作流程

  1. 打開數據庫:  indexedDB.open()

    var version = 1;
    var databaseName = "database";
    var request = window.indexedDB.open(databaseName, version);//這是一個異步操作,但是會立刻返回一個IDBOpenDBRequest對象。方法返回一個IDBRequest對象。這個對象通過三種事件error、success、upgradeneeded處理打開數據庫的操作結果。
    var db;
    
    /**
     * 新建數據庫與打開數據庫是同一個操作。
     * 如果要打開的數據庫不存在,則會先新建數據庫:
     *         1. 新建數據庫時調用 request.onupgradeneeded(因為這時版本從無到有,所以會觸發這個事件)
     *         2. 把數據庫版本設為 1
     *         3. 此時數據庫對象 db = e.target.result;
     * 新建數據庫后,就可以打開數據庫了,所以繼續調用 request.onsuccess
     * */
    request.onupgradeneeded = function(e) {
        db = e.target.result;
        console.log("onupgrageneeded");
        // 通常新建數據庫以后,第一件事是新建對象倉庫(即新建表),並設置主鍵
        var objectStore = db.createObjectStore("person", {
            keyPath: "id" //設置主鍵為 id
        });
    }
    
    /**
     * 如果要打開的數據庫存在,則會直接打開該數據庫
     * 此時數據庫對象 db = request.result;
     * */
    request.onsuccess = function(e) {
        db = request.result;
        console.log("success");
    }
    
    /**
     * 數據庫打開錯誤時調用此回調函數
     * */
    request.onerror = function(e) {
        console.log("error");
    }

  2. 新建數據庫:

    新建數據庫與打開數據庫是同一個操作。如果指定的數據庫不存在,就會新建。
    a. 新建對象倉庫(即新建表)。
    request.onupgradeneeded = function(e) {
        db = e.target.result;
        console.log("onupgrageneeded");
        // 通常,新建數據庫以后,第一件事是新建對象倉庫(即新建表),並設置主鍵
        var objectStore = db.createObjectStore("person", {
            keyPath: "id" //設置主鍵為 id
        });
    }
    b. 更好的寫法是先判斷一下,這張表格是否存在,如果不存在再新建。
    request.onupgradeneeded = function(e) {
        db = e.target.result;
        console.log("onupgrageneeded");
        // 通常新建數據庫以后,第一件事是新建對象倉庫(即新建表),並設置主鍵
        var objectStore;
        if(!db.objectStoreNames.contains(databaseName)) {//如果這個 對象倉庫/表 不存在,就新建
            objectStore = db.createObjectStore("person", {
                keyPath: "id" //設置主鍵為 id
            });
        }
    }
    c. 如果數據記錄里面沒有合適作為主鍵的屬性,可以讓 IndexedDB 自動生成主鍵(設置主鍵)。
    var objectStore = db.createObjectStore("person", { autoIncrement: true }); //指定主鍵為一個遞增的整數

    d. 新建數據庫后可以新建當前數據庫的索引,使用索引可以更方便的查詢數據。

    /**
     * 新建當前數據庫的索引
     * 必須在VersionChange監聽函數里調用
     * objectStore.createIndex(indexName, keyPath, objectParameters)
     * indexName:索引名
     * keyPath:主鍵
     * objectParameters:配置對象(可選)
     * unique:如果設為 true,將不允許重復的值
     * multiEntry:如果設為 true,對於有多個值的主鍵數組,每個值將在索引里面新建一個條目,否則主鍵數組對應一個條目。
     * 
     * */
    objectStore.createIndex("name","name",{unique:false});//可以重復
    objectStore.createIndex("age","age",{unique:false});//可以重復
    objectStore.createIndex("email","email",{unique:true});//不能重復

    使用索引查詢代碼如下:

    useIndex() {
        var db = this.db;
        var objectStore = db.transaction("person","readonly").objectStore("person");
        var index = objectStore.index("name");
        var request = index.get("張三"); //只返回第一個
        // var request = index.getAll("張三");//返回所有的 “張三”
        
        request.onsuccess = function(e){
            var result = e.target.result;
            if(result){
                console.log("result:",result);
                console.log("索引查詢成功");
            }else{
                console.log("索引查詢失敗");
            }
        }
    },
  3. 新增數據:

    新增數據指的是向對象倉庫寫入數據記錄。這需要通過事務完成。
    var obj1 = {id:1,name:"張三",age:24,email:"zhangsan@foxmail.com"};
    var obj2 = {id:2,name:"李四",age:30,email:"lisi@foxmail.com"};
    function addRecord(obj){
        var request = db.transaction(["person"],"readwrite") //寫入數據需要新建一個事務。新建時必須指定表格名稱和操作模式(“只讀”或“讀寫”)
        .objectStore("person") //新建事務以后,通過IDBTransaction.objectStore(name)方法,拿到 IDBObjectStore 對象
        .add(obj); //再通過表格對象的add()方法,向表格寫入一條記錄
        request.onsuccess = function(e){
            console.log("數據寫入成功");
        }
        request.onerror = function(e){
            console.log("數據寫入失敗");
        }
    }
    window.onload = function(){
        addRecord(obj1);
        addRecord(obj2);
    }

    注意:不加window.onload 可能存在異步問題,報undefined錯誤。

    執行過代碼后如果對象倉庫仍是空,刷新一下即可:

     


參考文章:

[1] https://www.shulanxt.com/doc/dbdoc/db-intro

[2] http://www.ruanyifeng.com/blog/2018/07/indexeddb.html

[3] https://wangdoc.com/javascript/bom/indexeddb.html

[4] https://www.bilibili.com/video/BV15J411H7GH

[5] https://developer.mozilla.org/zh-CN/docs/Web/API/IDBObjectStore

[6] https://zhuanlan.zhihu.com/p/399223337


免責聲明!

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



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