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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

indexedDB简单介绍

發(fā)布時間:2023/12/14 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 indexedDB简单介绍 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

indexedDB

一、其它幾種前端存儲:

1、cookie

HTTP cookie 通常也叫作 cookie,最初用于在客戶端存儲會話信息。這個規(guī)范要求服務(wù)器在響應(yīng)
HTTP 請求時,通過發(fā)送 Set-Cookie HTTP 頭部包含會話信息。例如, 下面是包含這個頭部的一個 HTTP
響應(yīng) :

HTTP/1.1 200 OK Content-type: text/html Set-Cookie: name=value Other-header: other-header-value

這個 HTTP 響應(yīng)會設(shè)置一個名為"name",值為"value"的 cookie。名和值在發(fā)送時都會經(jīng)過 URL
編碼。瀏覽器會存儲這些會話信息,并在之后的每個請求中都會通過 HTTP 頭部 cookie 再將它們發(fā)回服
務(wù)器,比如:

GET /index.jsl HTTP/1.1 Cookie: name=value Other-header: other-header-value

這些發(fā)送回服務(wù)器的額外信息可用于唯一標(biāo)識發(fā)送請求的客戶端。

cookie 是與特定域綁定的。設(shè)置 cookie 后,它會與請求一起發(fā)送到創(chuàng)建它的域。這個限制能保證
cookie 中存儲的信息只對被認(rèn)可的接收者開放,不被其他域訪問。因?yàn)?cookie 存儲在客戶端機(jī)器上,所以為保證它不會被惡意利用,瀏覽器會施加限制。 同時, cookie也不會占用太多磁盤空間。

cookie 在瀏覽器中是由以下參數(shù)構(gòu)成的(這些參數(shù)在 Set-Cookie 頭部中使用分號加空格隔開 ) :

  • 名稱:唯一標(biāo)識 cookie 的名稱。 cookie 名不區(qū)分大小寫,因此 myCookie 和 MyCookie 是同一
    個名稱。不過,實(shí)踐中最好將 cookie 名當(dāng)成區(qū)分大小寫來對待,因?yàn)橐恍┓?wù)器軟件可能這樣
    對待它們。 cookie 名必須經(jīng)過 URL 編碼。
  • :存儲在 cookie 里的字符串值。這個值必須經(jīng)過 URL 編碼。
  • : cookie 有效的域。發(fā)送到這個域的所有請求都會包含對應(yīng)的 cookie。這個值可能包含子域(如
    www.wrox.com),也可以不包含(如.wrox.com 表示對 wrox.com 的所有子域都有效)。如果不明
    確設(shè)置,則默認(rèn)為設(shè)置 cookie 的域。
  • 路徑:請求 URL 中包含這個路徑才會把 cookie 發(fā)送到服務(wù)器。例如,可以指定 cookie 只能由
    http://www.wrox.com/books/訪問,因此訪問 http://www.wrox.com/下的頁面就不會發(fā)送 cookie,即
    使請求的是同一個域。
  • 過期時間:表示何時刪除 cookie 的時間戳(即什么時間之后就不發(fā)送到服務(wù)器了)。默認(rèn)情況下,
    瀏覽器會話結(jié)束后會刪除所有 cookie。不過,也可以設(shè)置刪除 cookie 的時間。這個值是 GMT 格
    式( Wdy, DD-Mon-YYYY HH:MM:SS GMT),用于指定刪除 cookie 的具體時間。這樣即使關(guān)閉
    瀏覽器 cookie 也會保留在用戶機(jī)器上。把過期時間設(shè)置為過去的時間會立即刪除 cookie。
  • 安全標(biāo)志:設(shè)置之后,只在使用 SSL 安全連接的情況下才會把 cookie 發(fā)送到服務(wù)器。例如,請
    求https://www.wrox.com 會發(fā)送 cookie,而請求 http://www.wrox.com 則不會 ;
HTTP/1.1 200 OK Content-type: text/html Set-Cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com Other-header: other-header-value

這個頭部設(shè)置一個名為"name"的 cookie,這個 cookie 在 2007 年 1 月 22 日 7:10:24 過期,對
www.wrox.com 及其他 wrox.com 的子域(如 p2p.wrox.com)有效。
安全標(biāo)志 secure 是 cookie 中唯一的非名/值對,只需一個 secure 就可以了。比如:
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value; domain=.wrox.com; path=/; secure
Other-header: other-header-value
這里創(chuàng)建的 cookie 對所有 wrox.com 的子域及該域中的所有頁面有效(通過 path=/指定)。不過,
這個 cookie 只能在 SSL 連接上發(fā)送,因?yàn)樵O(shè)置了 secure 標(biāo)志。
要知道,域、路徑、過期時間和 secure 標(biāo)志用于告訴瀏覽器什么情況下應(yīng)該在請求中包含 cookie。
這些參數(shù)并不會隨請求發(fā)送給服務(wù)器,實(shí)際發(fā)送的只有 cookie 的名/值對 ;

在 JavaScript 中處理 cookie 比較麻煩,因?yàn)榻涌谶^于簡單,只有 BOM 的 document.cookie 屬性。 根據(jù)用法不同,該屬性的表現(xiàn)迥異。要使用該屬性獲取值時, document.cookie 返回包含頁面中所有 有效 cookie 的字符串(根據(jù)域、路徑、過期時間和安全設(shè)置),以分號分隔,如下面的例子所示: name1=value1;name2=value2;name3=value3 所有名和值都是 URL 編碼的,因此必須使用 decodeURIComponent()解碼。 在設(shè)置值時,可以通過 document.cookie 屬性設(shè)置新的 cookie 字符串。這個字符串在被解析后會 添加到原有 cookie 中。設(shè)置 document.cookie 不會覆蓋之前存在的任何 cookie,除非設(shè)置了已有的 cookie。設(shè)置 cookie 的格式如下,與 Set-Cookie 頭部的格式一樣: name=value; expires=expiration_time; path=domain_path; domain=domain_name; secure 在所有這些參數(shù)中,只有 cookie 的名稱和值是必需的。下面是個簡單的例子: document.cookie = "name=Nicholas"; 這行代碼會創(chuàng)建一個名為"name"的會話 cookie,其值為"Nicholas"。這個 cookie 在每次客戶端向 服務(wù)器發(fā)送請求時都會被帶上,在瀏覽器關(guān)閉時就會被刪除。雖然這樣直接設(shè)置也可以,因?yàn)椴恍枰?名稱或值中編碼任何字符,但最好還是使用 encodeURIComponent()對名稱和值進(jìn)行編碼,比如: document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas"); 要為創(chuàng)建的 cookie 指定額外的信息,只要像 Set-Cookie 頭部一樣直接在后面追加相同格式的字 符串即可: document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas") + "; domain=.wrox.com; path=/";

因?yàn)樵?JavaScript 中讀寫 cookie 不是很直觀,所以可以通過輔助函數(shù)來簡化相應(yīng)的操作。與 cookie
相關(guān)的基本操作有讀、寫和刪除。這些在 CookieUtil 對象中表示如下:

class CookieUtil {static get(name) {let cookieName = `${encodeURIComponent(name)}=`,cookieStart = document.cookie.indexOf(cookieName),cookieValue = null;if (cookieStart > -1){let cookieEnd = document.cookie.indexOf(";", cookieStart);if (cookieEnd == -1){cookieEnd = document.cookie.length;}cookieValue = decodeURIComponent(document.cookie.substring(cookieStart+ cookieName.length, cookieEnd));}return cookieValue;}static set(name, value, expires, path, domain, secure) {let cookieText =`${encodeURIComponent(name)}=${encodeURIComponent(value)}`if (expires instanceof Date) {cookieText += `; expires=${expires.toGMTString()}`;}if (path) {cookieText += `; path=${path}`;}if (domain) {cookieText += `; domain=${domain}`;}if (secure) {cookieText += "; secure";}document.cookie = cookieText;}static unset(name, path, domain, secure) {CookieUtil.set(name, "", new Date(0), path, domain, secure);} }; // 可以像下面這樣使用這些方法: // 設(shè)置 cookie CookieUtil.set("name", "Nicholas"); CookieUtil.set("book", "Professional JavaScript"); // 讀取 cookie alert(CookieUtil.get("name")); // "Nicholas" alert(CookieUtil.get("book")); // "Professional JavaScript" // 刪除 cookie CookieUtil.unset("name"); CookieUtil.unset("book"); // 設(shè)置有路徑、域和過期時間的 cookie CookieUtil.set("name", "Nicholas", "/books/projs/", "www.wrox.com", new Date("January 1, 2010")); // 刪除剛剛設(shè)置的 cookie CookieUtil.unset("name", "/books/projs/", "www.wrox.com"); // 設(shè)置安全 cookie CookieUtil.set("name", "Nicholas", null, null, null, true); // 這些方法通過處理解析和 cookie 字符串構(gòu)建,簡化了使用 cookie 存儲數(shù)據(jù)的操作

2、Storage

Web Storage 的定義了兩個對象: localStorage 和 sessionStorage。 localStorage 是永久存儲機(jī)制, sessionStorage 是跨會話的存儲機(jī)制。這兩種瀏覽器存儲 API 提供了在瀏覽器中不受頁面刷新影響而存儲數(shù)據(jù)的兩種方式。

Storage 類型用于保存名/值對數(shù)據(jù),直至存儲空間上限(由瀏覽器決定)。 Storage 的實(shí)例與其他
對象一樣,但增加了以下方法 :

  • clear():刪除所有值;不在 Firefox 中實(shí)現(xiàn)。
  • getItem(name):取得給定 name 的值
  • key(index):取得給定數(shù)值位置的名稱
  • removeItem(name):刪除給定 name 的名/值對
  • setItem(name, value):設(shè)置給定 name 的值。

sessionStorage:

因?yàn)?sessionStorage 對象是 Storage 的實(shí)例,所以可以通過使用 setItem()方法或直接給屬
性賦值給它添加數(shù)據(jù)。下面是使用這兩種方式的例子:
// 使用方法存儲數(shù)據(jù)
sessionStorage.setItem("name", "Nicholas");
// 使用屬性存儲數(shù)據(jù)
sessionStorage.book = "Professional JavaScript";

可以使用 getItem()或直接訪問屬性名來取得。下面是使用這兩種方式的例子:

// 使用方法取得數(shù)據(jù)
let name = sessionStorage.getItem("name");
// 使用屬性取得數(shù)據(jù)
let book = sessionStorage.book;

可以結(jié)合 sessionStorage 的 length 屬性和 key()方法遍歷所有的值:

for (let i = 0, len = sessionStorage.length; i < len; i++){let key = sessionStorage.key(i);let value = sessionStorage.getItem(key);alert(`${key}=`${value}`); } for (let key in sessionStorage){let value = sessionStorage.getItem(key);alert(`${key}=${value}`); }

要從 sessionStorage 中刪除數(shù)據(jù),可以使用 delete 操作符直接刪除對象屬性,也可以使用
removeItem()方法。下面是使用這兩種方式的例子:

// 使用 delete 刪除值 delete sessionStorage.name; // 使用方法刪除值 sessionStorage.removeItem("book");

sessionStorage 對象應(yīng)該主要用于存儲只在會話期間有效的小塊數(shù)據(jù)。如果需要跨會話持久存儲
數(shù)據(jù),可以使用 globalStorage 或 localStorage

存儲在 localStorage 中的數(shù)據(jù)會保留到通過 JavaScript 刪除或者用戶清除瀏覽器緩存。 localStorage 數(shù)據(jù)不受頁面刷新影響,也不會因關(guān)閉窗口、標(biāo)簽頁或重新啟動瀏覽器而丟失。

存儲事件

每當(dāng) Storage 對象發(fā)生變化時,都會在文檔上觸發(fā) storage 事件。使用屬性或 setItem()設(shè)置
值、使用 delete 或 removeItem()刪除值,以及每次調(diào)用 clear()時都會觸發(fā)這個事件。這個事件的
事件對象有如下 4 個屬性。

  • domain:存儲變化對應(yīng)的域。

  • key:被設(shè)置或刪除的鍵。

  • newValue:鍵被設(shè)置的新值,若鍵被刪除則為 null。

  • oldValue:鍵變化之前的值。

    可以使用如下代碼監(jiān)聽 storage 事件:

    window.addEventListener("storage",(event) => alert('Storage changed for ${event.domain}' ));

    對于 sessionStorage 和 localStorage 上的任何更改都會觸發(fā) storage 事件,但 storage 事
    件不會區(qū)分這兩者。

二、indexedDB簡介

IndexedDB和傳統(tǒng)的關(guān)系型數(shù)據(jù)不同的是,它是一個key-value型的數(shù)據(jù)庫。

value可以是復(fù)雜的結(jié)構(gòu)體對象,key可以是對象的某些屬性值也可以是其他的對象(包括二進(jìn)制對象)。你可以使用對象中的任何屬性做為index,以加快查找。

IndexedDB是自帶transaction的,所有的數(shù)據(jù)庫操作都會綁定到特定的事務(wù)上,并且這些事務(wù)是自動提交了,IndexedDB并不支持手動提交事務(wù)。

IndexedDB API大部分都是異步的,在使用異步方法的時候,API不會立馬返回要查詢的數(shù)據(jù),而是返回一個callback。

異步API的本質(zhì)是向數(shù)據(jù)庫發(fā)送一個操作請求,當(dāng)操作完成的時候,會收到一個DOM event,通過該event,我們會知道操作是否成功,并且獲得操作的結(jié)果。

IndexedDB是一種 NoSQL 數(shù)據(jù)庫,和關(guān)系型數(shù)據(jù)庫不同的是,IndexedDB是面向?qū)ο蟮?#xff0c;它存儲的是Javascript對象。

IndexedDB還有一個很重要的特點(diǎn)是其同源策略,每個源都會關(guān)聯(lián)到不同的數(shù)據(jù)庫集合,不同源是不允許訪問其他源的數(shù)據(jù)庫,從而保證了IndexedDB的安全性。

三、使用原因:開發(fā)者需要在本地進(jìn)行永久存儲

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

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

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

四、indexedDB的相關(guān)操作

// 假如一開始有這樣的數(shù)據(jù)需要存儲 let data = [{id: 1,name: "lzc",age: 18,sex: "man",addTime: "2021-2-1"},{id: 2,name: "cb",age: 19,sex: "man",addTime: "2021-2-2"},{id: 3,name: "kj",age: 20,sex: "woman",addTime: "2021-2-3"},{id: 4,name: "juanjuan",age: 21,sex: "woman",addTime: "2021-2-4"} ]

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

/* 不同的瀏覽器對于IndexedDB有不同的實(shí)現(xiàn),正常來說,我們可以使用window.indexedDB來獲取到瀏覽器的indexedDB對象。但是對于某些瀏覽器來說,還沒有使用標(biāo)準(zhǔn)的window.indexedDB,而是用帶前綴的實(shí)現(xiàn)使用IndexedDB第一步,就是創(chuàng)建或打開一個數(shù)據(jù)庫。我們使用window.indexedDB.open(DBName)這個API來打進(jìn)行操作。 */ window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;if (!window.indexedDB) {console.log("Your browser doesn't support a stable version of IndexedDB. Such and such feature will not be available."); } else {const request = window.indexedDB.open('people');request.onupgradeneeded = function (event) {}request.onsuccess = function(event) {console.log(request === event.target) // true}request.onerror = function(event) {} }
  • 調(diào)用此接口時,如果當(dāng)前數(shù)據(jù)庫不存在,則會創(chuàng)建一個新的數(shù)據(jù)庫;
  • 當(dāng)數(shù)據(jù)庫建立連接時,會返回一個IDBOpenDBRequest對象。
  • 在連接建立成功時,會觸發(fā)onsuccess事件,其中函數(shù)參數(shù)event的target屬性就是request對象。
  • 而在數(shù)據(jù)庫創(chuàng)建或者版本更新時,會觸發(fā)onupgradeneeded事件。

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

window.indexedDB.open的第二個參數(shù)即為版本號。在不指定的情況下,默認(rèn)版本號為1。

const request = window.indexedDB.open('people', 2);

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

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

3、存儲空間操作

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

var request = window.indexedDB.open('people', 1);request.onupgradeneeded = function (event) {console.log(request === event.target) // truevar db = event.target.result;var objectStore = db.createObjectStore('user', {keyPath: 'id', autoIncrement: true});// 可以循環(huán)遍歷,給對象數(shù)組或者對象的每個鍵都生成索引(每個索引里面的數(shù)據(jù)項(xiàng)的排序按索引的升序來排列,索引沒有順序可言,就按原始順序)if (Object.prototype.toString.call(data) === "[object Array]" && data.length) {for (let i in data[0]) {objectStore.createIndex(i, i, { unique: false })}} else if (Object.prototype.toString.call(data) === "[object object]") {for (let i in data) {objectStore.createIndex(i, i, { 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ù),存儲空間的名稱,即我們上面的user。
  • 第二個參數(shù),指定存儲的keyPath值為存儲對象的某個屬性,這個屬性能夠在獲取存儲空間數(shù)據(jù)的時候當(dāng)做key值使用。autoIncrement指定了key值是否自增(當(dāng)key值為默認(rèn)的從1開始到2^53的整時)。
  • 而createIndex能夠給當(dāng)前的存儲空間設(shè)置一個索引。它接受三個參數(shù):

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

    1、事務(wù)transaction

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

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

    我們創(chuàng)建一個事務(wù)時,需要從上面選擇一種模式,如果不指定的話,則默認(rèn)為只讀模式。

    const transaction = db.transaction(['user'], 'readwrite');

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

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

    當(dāng)存儲空間objectStore初始化完成后,我們可以把數(shù)據(jù)放入存儲空間中??梢允褂?add()或 put()寫入數(shù)據(jù)。這兩個方法都接收一個參數(shù), 即要存儲的對象,并把對象保存到對象存儲。這兩個方法只在對象存儲中已存在同名的鍵時有區(qū)別。這 種情況下,add()會導(dǎo)致錯誤,而 put()會簡單地重寫該對象。

    var request = window.indexedDB.open('people', 1);request.onsuccess = function (event) {var db = event.target.result;var transaction = db.transaction(['user'], 'readwrite');var objectStore = transaction.objectStore('user');for (let item of data) {objectStore.add(item);} }

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

    // 1、createObjectStore第二個參數(shù)里加 { autoIncrement: true },這個時候key使用從1開始的自增數(shù),遍歷出來的數(shù)據(jù)和原始要存儲的數(shù)據(jù)順序一致; // 2、objectStore.add(item, item.name); 指定了keyPath值,這時候遍歷出來的數(shù)據(jù)順序,可能和原始的不一樣,這里是按照keyPath值字母語序來排列的;這里寫不寫{ autoIncrement: true }都可以; // 3、createObjectStore第二個參數(shù)里加 { keyPath: "name" },這里不能再在objectStore.add(item)里面添加第二個參數(shù),即使這里第二個參數(shù)添加的和createObjectStore里面的第二個參數(shù)的keyPath的一致;

    上面的只影響user對象存儲里面的排序,其它索引的排序只和自己的索引有關(guān);

    3、查找數(shù)據(jù)
    1、通過特定值獲取數(shù)據(jù)(只能獲取單條數(shù)據(jù))
    • 這里默認(rèn)只能獲取通過createObjectStore的第二參數(shù)的keyPath設(shè)置的參數(shù)的user對象存儲的數(shù)據(jù),其它索引的無法查出;
    • 或者使用index方法改變默認(rèn)索引,比如let store = objectStore.index(“age”),再用store.get(18)就可以通過age來查詢了(前提是用createIndex創(chuàng)建了age索引的對象存儲,才能使用objectStore.index(“age”),才能查詢);
    var request = window.indexedDB.open('people', 1);request.onsuccess = function (event) {var db = event.target.result;var transaction = db.transaction(['user'], 'readwrite');var objectStore = transaction.objectStore('user');var request = objectStore.get(1);request.onsuccess = function (event) {//打印搜索的結(jié)果console.log(e.target.result);};request.onerror = function (event) {// 錯誤處理!}; }
    2、通過游標(biāo)獲取數(shù)據(jù)(獲取多條數(shù)據(jù))

    當(dāng)你需要遍歷整個存儲空間中的數(shù)據(jù)時,你就需要使用到游標(biāo),與傳統(tǒng)數(shù)據(jù)庫查詢不同,游標(biāo)不會事先收集所有結(jié)果。相反,游標(biāo)指向 第一個結(jié)果,并在接到指令前不會主動查找下一條數(shù)據(jù)

    var request = window.indexedDB.open('people', 1);request.onsuccess = function (event) {var db = event.target.result;var transaction = db.transaction(['user'], 'readwrite');var objectStore = transaction.objectStore('user');var request = objectStore.openCursor();request.onsuccess = function (event) {var cursor = event.target.result;if (cursor) {console.log(cursor.key, cursor.value);cursor.continue();}};request.onerror = function (event) {// 錯誤處理!}; }

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

    openCursor和openKeyCursor有兩個參數(shù):**openKeyCursor**遍歷出來的值里面沒有value對象值,其它和openCursor一致

  • 第一個參數(shù)(占位時可以使用null),遍歷范圍,指定游標(biāo)的訪問范圍。該范圍通過一個IDBKeyRange參數(shù)的方法來獲取。 遍歷范圍參數(shù)具體示例如下: ===>這種鍵范圍只能比較其鍵能比較大小的對象存儲或者only這種
  • // 匹配值 key === 1 const singleKeyRange = IDBKeyRange.only(1); // 匹配值 key >= 1,lowerBound用于設(shè)定結(jié)果集的下限,閉集 const lowerBoundKeyRange = IDBKeyRange.lowerBound(1); // 匹配值 key > 1,lowerBound用于設(shè)定結(jié)果集的下限,包含該值,設(shè)置第二個參數(shù)為true時,變?yōu)殚_集 const lowerBoundOpenKeyRange = IDBKeyRange.lowerBound(1, true); // 匹配值 key < 2,upperBound用于設(shè)定結(jié)果集的上限,包含該值,設(shè)置第二個參數(shù)為true時,變?yōu)殚_集 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ù),默認(rèn)值是next,遍歷順序,指定游標(biāo)遍歷時的順序和處理相同id(keyPath屬性指定字段)重復(fù)時的處理方法。改范圍通過特定的小寫字符串(IDBCursor的常量已經(jīng)棄用)來獲取。其中:
    • next,從前往后獲取所有數(shù)據(jù)(重復(fù)值也會遍歷出來)
    • prev,從后往前獲取所有數(shù)據(jù)(重復(fù)值也會遍歷出來)
    • nextunique,從前往后獲取數(shù)據(jù)(重復(fù)數(shù)據(jù)只取第一條,索引重復(fù)即認(rèn)為重復(fù),下同)
    • prevunique,從后往前獲取數(shù)據(jù)(重復(fù)數(shù)據(jù)只取第一條)
    var request = window.indexedDB.open('test', 1);request.onsuccess = function (event) {var db = event.target.result;var transaction = db.transaction(['user'], 'readwrite');var objectStore = transaction.objectStore('user');var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound(1, false);var request = objectStore.openCursor(lowerBoundOpenKeyRange, "prev");request.onsuccess = function (event) {var cursor = event.target.result;if (cursor) {console.log(cursor.value);cursor.continue();}};request.onerror = function (event) {// 錯誤處理!}; }
    4、使用索引

    在前面構(gòu)建數(shù)據(jù)庫時,我們創(chuàng)建了所有的索引。現(xiàn)在我們也可以通過索引來進(jìn)行數(shù)據(jù)檢索。他的本質(zhì)還是通過之前獲取數(shù)據(jù)的API來進(jìn)行,只是將原來使用的keyPath屬性轉(zhuǎn)換成為了索引指定的屬性。

    var request = window.indexedDB.open('test', 1);request.onsuccess = function (event) {var db = event.target.result;var transaction = db.transaction(['user'], 'readwrite');var objectStore = transaction.objectStore('user');// 使用索引var index = objectStore.index('name');// 第一種,get方法index.get('a').onsuccess = function (event) {console.log(event.target.result);}// 第二種,普通游標(biāo)方法index.openCursor().onsuccess = function (event) {console.log('openCursor:', event.target.result.value);}// 第三種,鍵游標(biāo)方法,該方法與第二種的差別為:普通游標(biāo)帶有value值表示獲取的數(shù)據(jù),而鍵游標(biāo)沒有index.openKeyCursor().onsuccess = function (event) {console.log('openKeyCursor:', event.target.result.key);} }
    5、修改數(shù)據(jù)===>修改時,須帶上這條數(shù)據(jù)的索引鍵

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

    使用objectStore.put方法時,參數(shù)為已存在的鍵,即為修改,為不存在的鍵時,即為增加;

    這里不能像查詢一樣,通過store.index()來修改索引,index上只有g(shù)et方法

    var transaction = db.transaction(['user'], 'readwrite'); var store = transaction.objectStore("user");// 用put增加一條新數(shù)據(jù) var request1 = store.put({id: 5,name: "李志聰",age: 22,sex: "man",addTime: "2021-2-5" });// 用put增加一條新數(shù)據(jù),改sex描述===>是修改時,須帶上這條數(shù)據(jù)的索引鍵 var request2 = store.put({id: 2,name: "lzc",age: 18,sex: "男",addTime: "2021-2-2" });request1.onsuccess = function (event) {}
    6、刪除數(shù)據(jù)
    var transaction = db.transaction(['user'], 'readwrite'); var store = transaction.objectStore("user");var request = store.delete(對應(yīng)某一條keyPath值);request.onsuccess = function (event) {}
    7、關(guān)閉數(shù)據(jù)庫
    // 比如在destoryed鉤子里面可以關(guān)閉數(shù)據(jù)庫 db.close();

    五、安全相關(guān)

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

    六、dexie.js庫的使用

    dexie.js:A Minimalistic Wrapper for IndexedDB

    基于indexDB的Dexie數(shù)據(jù)庫

    // 下面配一個簡單的演示// 創(chuàng)建一個數(shù)據(jù)庫 若數(shù)據(jù)庫已存在則為打開 // 打開數(shù)據(jù)庫時,會判斷當(dāng)前version值是否大于已經(jīng)存在的version值,若大于則會upgrade即升到最高版本 var db = new Dexie("mydb");// 設(shè)定版本,添加一個person表,里面有自增的id主鍵,有name和age兩個索引 // 注意:不要像在SQL中那樣聲明所有列。只聲明要索引的屬性,即要在where(…)查詢中使用的屬性。 db.version(1).stores({person: "++id, name, age" })// 增加(還是使用上面的數(shù)據(jù)進(jìn)行存儲) for(let item of data) {db.person.add(item) }// 修改 setTimeout(() => {db.person.put({id: 2,name: "聰波",age: 18,sex: "boy",addTime: "2021-2-2"})console.log(db.person.get(2)) // 一個promise對象// 普通查詢db.person.get(2).then(res => {console.log("查詢的結(jié)果為===>", res)}) }, 1000)// 帶條件查詢 setTimeout(() => {// adove、aboveOrEqual、below、belowOrEqual、between、equalsdb.person.where("age").aboveOrEqual(18).toArray().then(res => {console.log("年齡大于等于18歲的有===>", res)}) }, 2000)// 刪除 setTimeout(() => {// 刪除第一條db.person.delete(1);db.person.get(1).then(res => {console.log("第一條數(shù)據(jù)===>", res)}) }, 3000)setTimeout(() => {db.close();console.log("要是數(shù)據(jù)庫沒有關(guān)閉,下面將打印第三天數(shù)據(jù)");db.person.get(3).then(res => {console.log("第三條數(shù)據(jù)===>", res)}) }, 4000)

    總結(jié)

    以上是生活随笔為你收集整理的indexedDB简单介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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