日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

数据库基础:IndexedDB

發(fā)布時間:2023/12/14 数据库 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库基础:IndexedDB 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、概述

本文通過對IndexedDB的使用方法和使用場景進行相關介紹,對常見的問題進行解答。

二、原因:開發(fā)者需要在本地進行永久存儲

當我們進行一些較大的SPA頁面開發(fā)時,我們會需要進行一些數(shù)據(jù)的本地存儲。

當數(shù)據(jù)量不大時,我們可以通過SessionStorage或者LocalStorage來進行存儲,但是當數(shù)據(jù)量較大,或符合一定的規(guī)范時,我們可以使用數(shù)據(jù)庫來進行數(shù)據(jù)的存儲。

在瀏覽器提供的數(shù)據(jù)庫中,共有web sql和IndexedDB兩種。相較于HTML5已經(jīng)廢棄的web sql來說,更推薦大家使用IndexedDB。

三、結構

下面,我們通過一張圖來了解下,IndexedDB整體的結構。

類比sql型數(shù)據(jù)庫,IndexedDB中的DB(數(shù)據(jù)庫)就是sql中的DB,而Object Store(存儲空間)則是數(shù)據(jù)表,Item則等于表中的一條記錄。

四、使用IndexedDB

現(xiàn)在,我們將其根據(jù)IndexedDB的結構來對其操作進行介紹,能讓大家對這個存儲空間有一個初步的了解。我們主要介紹:

  • 數(shù)據(jù)庫操作
  • 數(shù)據(jù)表操作
  • 數(shù)據(jù)操作

1.數(shù)據(jù)庫操作

創(chuàng)建或打開數(shù)據(jù)庫

使用IndexedDB第一步,就是創(chuàng)建或打開一個數(shù)據(jù)庫。我們使用window.indexedDB.open(DBName)這個API來打進行操作。具體示例如下:

const request = window.indexedDB.open('test');request.onupgradeneeded = function (event) {}request.onsuccess = function(event) {//request === event.target; } request.onerror = function(event) {} 復制代碼

調(diào)用此接口時,如果當前數(shù)據(jù)庫不存在,則會創(chuàng)建一個新的數(shù)據(jù)庫。

當數(shù)據(jù)庫建立連接時,會返回一個IDBOpenDBRequest對象。

在連接建立成功時,會觸發(fā)onsuccess事件,其中函數(shù)參數(shù)event的target屬性就是request對象。

而在數(shù)據(jù)庫創(chuàng)建或者版本更新時,會觸發(fā)onupgradeneeded事件。

更新數(shù)據(jù)庫版本號

window.indexedDB.open的第二個參數(shù)即為版本號。在不指定的情況下,默認版本號為1。具體示例如下:

const request = window.indexedDB.open('test', 2); 復制代碼

在需要更新數(shù)據(jù)庫的schema(模式)時,需要更新版本號。此時我們指定一個高于之前版本的版本號,就會觸發(fā)onupgradeneeded事件。類似的,當此數(shù)據(jù)庫不存在時,也會觸發(fā)此事件并且將版本更新到置頂版本。

我們需要注意的是,版本號是一個Unsigned long long數(shù)字,這意味著它可以是一個非常大的整數(shù)。但是,它不能是一個小數(shù),否則它將會被轉為最近的整數(shù),同時有可能導致onUpgradeneeded事件不觸發(fā)(bug)。

2.存儲空間操作

創(chuàng)建存儲空間

我們使用createObjectStore來創(chuàng)建一個存儲空間。同時,使用createIndex來創(chuàng)建它的索引。具體示例如下:

var request = window.indexedDB.open('test', 1);request.onupgradeneeded = function (event) {var db = event.target.result;var objectStore = db.createObjectStore('table1', {keyPath: 'id', autoIncrement: true});objectStore.createIndex('name', 'name', {unique: false}); }request.onerror = function (event) {alert("Why didn't you allow my web app to use IndexedDB?!"); }; 復制代碼

注:只能在onupgradeneeded回調(diào)函數(shù)中創(chuàng)建存儲空間,而不能在數(shù)據(jù)庫打開后的success回調(diào)函數(shù)中創(chuàng)建。

通過createObjectStore能夠創(chuàng)建一個存儲空間。接受兩個參數(shù):

  • 第一個參數(shù),存儲空間的名稱,即我們上面的customers。
  • 第二個參數(shù),指定存儲的keyPath值為存儲對象的某個屬性,這個屬性能夠在獲取存儲空間數(shù)據(jù)的時候當做key值使用。autoIncrement指定了key值是否自增(當key值為默認的從1開始到2^53的整數(shù)時)。
  • 而createIndex能夠給當前的存儲空間設置一個索引。它接受三個參數(shù):

  • 第一個參數(shù),索引的名稱。
  • 第二個參數(shù),指定根據(jù)存儲數(shù)據(jù)的哪一個屬性來構建索引。
  • 第三個屬性, options對象,其中屬性unique的值為true表示不允許索引值相等。
  • 2.數(shù)據(jù)操作

    事務

    在IndexedDB中,我們也能夠使用事務來進行數(shù)據(jù)庫的操作。事務有三個模式(常量已經(jīng)棄用):

    • readOnly,只讀。
    • readwrite,讀寫。
    • versionchange,數(shù)據(jù)庫版本變化。

    我們創(chuàng)建一個事務時,需要從上面選擇一種模式,如果不指定的話,則默認為只讀模式。具體示例如下:

    const transaction = db.transaction(['customers'], 'readwrite'); 復制代碼

    事務函數(shù)transaction的第一個參數(shù)為需要關聯(lián)的存儲空間,第二個可選參數(shù)為事務模式。與上面類似,事務成功時也會觸發(fā)onsuccess函數(shù),失敗時觸發(fā)onerror函數(shù)。

    事務的操作都是原子性的。

    增加數(shù)據(jù)

    當存儲空間初始化完成后,我們可以把數(shù)據(jù)放入存儲空間中。直接調(diào)用add方法就可以將數(shù)據(jù)放入存儲空間內(nèi),具體示例如下:

    var request = window.indexedDB.open('test', 1);request.onsuccess = function (event) {var db = event.target.result;var transaction = db.transaction(['table1'], 'readwrite');var objectStore = transaction.objectStore('table1');var index = objectStore.index('name');objectStore.add({name: 'a', age: 10});objectStore.add({name: 'b', age: 20}); } 復制代碼

    注:add方法中的第二個參數(shù)key值是指定存儲空間中的keyPath值,如果data中包含keyPath值或者此值為自增值,那么可以略去此參數(shù)。

    查找數(shù)據(jù)

    通過特定值獲取數(shù)據(jù)

    當我們需要從存儲空間獲取數(shù)據(jù)時,我們可以通過以下的方法:

    var request = window.indexedDB.open('test', 1);request.onsuccess = function (event) {var db = event.target.result;var transaction = db.transaction(['table1'], 'readwrite');var objectStore = transaction.objectStore('table1');var request = objectStore.get(1);request.onsuccess = function (event) {// 對 request.result 做些操作!console.log(request.result);};request.onerror = function (event) {// 錯誤處理!}; } 復制代碼

    通過游標獲取數(shù)據(jù)

    當你需要遍歷整個存儲空間中的數(shù)據(jù)時,你就需要使用到游標。游標使用方法如下:

    var request = window.indexedDB.open('test', 1);request.onsuccess = function (event) {var db = event.target.result;var transaction = db.transaction(['table1'], 'readwrite');var objectStore = transaction.objectStore('table1');var request = objectStore.openCursor();request.onsuccess = function (event) {var cursor = event.target.result;if (cursor) {// 使用Object.assign方法是為了避免控制臺打印時出錯console.log(Object.assign(cursor.value));cursor.continue();}};request.onerror = function (event) {// 錯誤處理!}; } 復制代碼

    使用游標時有一個需要注意的地方,當游標遍歷整個存儲空間但是并未找到給定條件的值時,仍然會觸發(fā)onsuccess函數(shù)。

    openCursor和openKeyCursor有兩個參數(shù):

  • 第一個參數(shù),遍歷范圍,指定游標的訪問范圍。該范圍通過一個IDBKeyRange參數(shù)的方法來獲取。

    遍歷范圍參數(shù)具體示例如下:

  • // 匹配值 key === 1 const singleKeyRange = IDBKeyRange.only(1);// 匹配值 key >= 1 const lowerBoundKeyRange = IDBKeyRange.lowerBound(1);// 匹配值 key > 1 const lowerBoundOpenKeyRange = IDBKeyRange.lowerBound(1, true);// 匹配值 key < 2 const upperBoundOpenKeyRange = IDBKeyRange.upperBound(2, true);// 匹配值 key >= 1 && key < 2 const boundKeyRange = IDBKeyRange.bound(1, 2, false, true);index.openCursor(boundKeyRange).onsuccess = function(event) {const cursor = event.target.result;if (cursor) {// Do something with the matches.cursor.continue();} }; 復制代碼
  • 第二個參數(shù),遍歷順序,指定游標遍歷時的順序和處理相同id(keyPath屬性指定字段)重復時的處理方法。改范圍通過特定的字符串(IDBCursor的常量已經(jīng)棄用)來獲取。其中:

    • next,從前往后獲取所有數(shù)據(jù)(包括重復數(shù)據(jù))
    • prev,從后往前獲取所有數(shù)據(jù)(包括重復數(shù)據(jù))
    • nextunique,從前往后獲取數(shù)據(jù)(重復數(shù)據(jù)只取第一條,索引重復即認為重復,下同)
    • prevunique,從后往前獲取數(shù)據(jù)(重復數(shù)據(jù)只取第一條)

    遍歷順序參數(shù)具體示例如下:

  • var request = window.indexedDB.open('test', 1);request.onsuccess = function (event) {var db = event.target.result;var transaction = db.transaction(['table1'], 'readwrite');var objectStore = transaction.objectStore('table1');var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound(1, false);var request = objectStore.openCursor(lowerBoundOpenKeyRange, IDBCursor.PREV);request.onsuccess = function (event) {var cursor = event.target.result;if (cursor) {// 使用Object.assign方法是為了避免控制臺打印時出錯console.log(Object.assign(cursor.value));cursor.continue();}};request.onerror = function (event) {// 錯誤處理!}; } 復制代碼

    使用索引

    在前面構建數(shù)據(jù)庫時,我們創(chuàng)建了兩個索引。現(xiàn)在我們也可以通過索引來進行數(shù)據(jù)檢索。他的本質(zhì)還是通過之前獲取數(shù)據(jù)的API來進行,只是將原來使用的keyPath屬性轉換成為了索引指定的屬性。具體示例如下:

    var request = window.indexedDB.open('test', 1);request.onsuccess = function (event) {var db = event.target.result;var transaction = db.transaction(['table1'], 'readwrite');var objectStore = transaction.objectStore('table1');var index = objectStore.index('name');// 第一種,get方法index.get('a').onsuccess = function (event) {console.log(event.target.result);}// 第二種,普通游標方法index.openCursor().onsuccess = function (event) {console.log('openCursor:', event.target.result.value);}// 第三種,鍵游標方法,該方法與第二種的差別為:普通游標帶有value值表示獲取的數(shù)據(jù),而鍵游標沒有index.openKeyCursor().onsuccess = function (event) {console.log('openKeyCursor:', event.target.result);} } 復制代碼

    修改數(shù)據(jù)

    當需要修改存儲空間中的數(shù)據(jù)時,我們可以使用以下的API:

    var objectStore = transaction.objectStore("customers");var request = objectStore.put(data);request.onsuccess = function (event) {} 復制代碼

    注:put方法不僅能夠修改現(xiàn)有數(shù)據(jù),也能夠往存儲空間中增加新的數(shù)據(jù)。

    刪除數(shù)據(jù)

    當我們需要刪除已經(jīng)無用的數(shù)據(jù)時,我們可以通過以下方法:

    var objectStore = transaction.objectStore("customers");var request = objectStore.delete(name);request.onsuccess = function (event) {} 復制代碼

    異常處理

    在瀏覽器有如下操作的情況下,indexedDB可能會出現(xiàn)異常:

    • 用戶清除瀏覽器緩存
    • 存儲空間超過大小限制

    此時,需要對錯誤進行捕獲,并且對用戶進行提示。此章節(jié)不是本文重點,再此略過。

    五、擴展須知

    1.取值相關

    key值能夠接受的數(shù)據(jù)類型

    在IndexedDB中,鍵值對中的key值可以接受以下幾種類型的值:

    • number
    • data
    • string
    • binary
    • array

    key path能夠接受的數(shù)據(jù)類型

    當一個key值變?yōu)橹麈I,即keyPath時,它的值就只能是以下幾種:

    • Blob
    • File
    • Array
    • String

    注:空格不能出現(xiàn)在key path中。

    value能夠接受的數(shù)據(jù)類型

    在IndexedDB中,value能夠接受ECMA-262中所有的類型的值,例如String,Date,ImageDate等。

    2.事務相關

    事務中斷后,會不會影響key值的自增

    IndexedDB在沒有指定key值的時候就會采用自增的key值。如果一個事務在中途中斷,那么key值的自增將會從中斷的事務開始前的key開始。

    3.安全相關

    IndexedDB也受到瀏覽器同源策略的限制。

    4.用戶相關

    清空緩存

    用戶在清除瀏覽器緩存時,可能會清除IndexedDB中相關的數(shù)據(jù)。

    訪問權限

    部分瀏覽器如Safari手機版隱私模式在訪問IndexedDB時,可能會出現(xiàn)由于沒有權限而導致的異常(LocalStorage也會),需要進行異常處理。

    六、總結

    IndexedDB在本地存儲中有著無可替代的作用,是替代關系型數(shù)據(jù)庫web sql的產(chǎn)品,能夠對大量數(shù)據(jù)進行存儲。在許多需要運用離線存儲的場景下,它能夠給我們提供有效的支撐。

    但是,IndexedDB在使用過程中仍然需要避免可能會出現(xiàn)的一些問題,或者對可能導致的不利影響有一定的容錯處理。這樣才不會對應用產(chǎn)生重大影響。

    參考轉載:https://juejin.cn/post/6844903570005835789

    總結

    以上是生活随笔為你收集整理的数据库基础:IndexedDB的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。