W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
隨著瀏覽器的處理能力不斷增強(qiáng),越來(lái)越多的網(wǎng)站開(kāi)始考慮,將大量數(shù)據(jù)儲(chǔ)存在客戶端,這樣可以減少用戶等待從服務(wù)器獲取數(shù)據(jù)的時(shí)間。
現(xiàn)有的瀏覽器端數(shù)據(jù)儲(chǔ)存方案,都不適合儲(chǔ)存大量數(shù)據(jù):cookie不超過(guò)4KB,且每次請(qǐng)求都會(huì)發(fā)送回服務(wù)器端;Window.name屬性缺乏安全性,且沒(méi)有統(tǒng)一的標(biāo)準(zhǔn);localStorage在2.5MB到10MB之間(各家瀏覽器不同)。所以,需要一種新的解決方案,這就是IndexedDB誕生的背景。
通俗地說(shuō),IndexedDB就是瀏覽器端數(shù)據(jù)庫(kù),可以被網(wǎng)頁(yè)腳本程序創(chuàng)建和操作。它允許儲(chǔ)存大量數(shù)據(jù),提供查找接口,還能建立索引。這些都是localStorage所不具備的。就數(shù)據(jù)庫(kù)類型而言,IndexedDB不屬于關(guān)系型數(shù)據(jù)庫(kù)(不支持SQL查詢語(yǔ)句),更接近NoSQL數(shù)據(jù)庫(kù)。
IndexedDB具有以下特點(diǎn)。
(1)鍵值對(duì)儲(chǔ)存。 IndexedDB內(nèi)部采用對(duì)象倉(cāng)庫(kù)(object store)存放數(shù)據(jù)。所有類型的數(shù)據(jù)都可以直接存入,包括JavaScript對(duì)象。在對(duì)象倉(cāng)庫(kù)中,數(shù)據(jù)以“鍵值對(duì)”的形式保存,每一個(gè)數(shù)據(jù)都有對(duì)應(yīng)的鍵名,鍵名是獨(dú)一無(wú)二的,不能有重復(fù),否則會(huì)拋出一個(gè)錯(cuò)誤。
(2)異步。 IndexedDB操作時(shí)不會(huì)鎖死瀏覽器,用戶依然可以進(jìn)行其他操作,這與localStorage形成對(duì)比,后者的操作是同步的。異步設(shè)計(jì)是為了防止大量數(shù)據(jù)的讀寫,拖慢網(wǎng)頁(yè)的表現(xiàn)。
(3)支持事務(wù)。 IndexedDB支持事務(wù)(transaction),這意味著一系列操作步驟之中,只要有一步失敗,整個(gè)事務(wù)就都取消,數(shù)據(jù)庫(kù)回到事務(wù)發(fā)生之前的狀態(tài),不存在只改寫一部分?jǐn)?shù)據(jù)的情況。
(4)同域限制 IndexedDB也受到同域限制,每一個(gè)數(shù)據(jù)庫(kù)對(duì)應(yīng)創(chuàng)建該數(shù)據(jù)庫(kù)的域名。來(lái)自不同域名的網(wǎng)頁(yè),只能訪問(wèn)自身域名下的數(shù)據(jù)庫(kù),而不能訪問(wèn)其他域名下的數(shù)據(jù)庫(kù)。
(5)儲(chǔ)存空間大 IndexedDB的儲(chǔ)存空間比localStorage大得多,一般來(lái)說(shuō)不少于250MB。IE的儲(chǔ)存上限是250MB,Chrome和Opera是剩余空間的某個(gè)百分比,F(xiàn)irefox則沒(méi)有上限。
(6)支持二進(jìn)制儲(chǔ)存。 IndexedDB不僅可以儲(chǔ)存字符串,還可以儲(chǔ)存二進(jìn)制數(shù)據(jù)。
目前,Chrome 27+、Firefox 21+、Opera 15+和IE 10+支持這個(gè)API,但是Safari完全不支持。
下面的代碼用來(lái)檢查瀏覽器是否支持這個(gè)API。
瀏覽器原生提供indexedDB對(duì)象,作為開(kāi)發(fā)者的操作接口。indexedDB.open方法用于打開(kāi)數(shù)據(jù)庫(kù)。
open方法的第一個(gè)參數(shù)是數(shù)據(jù)庫(kù)名稱,格式為字符串,不可省略;第二個(gè)參數(shù)是數(shù)據(jù)庫(kù)版本,是一個(gè)大于0的正整數(shù)(0將報(bào)錯(cuò))。上面代碼表示,打開(kāi)一個(gè)名為test、版本為1的數(shù)據(jù)庫(kù)。如果該數(shù)據(jù)庫(kù)不存在,則會(huì)新建該數(shù)據(jù)庫(kù)。如果省略第二個(gè)參數(shù),則會(huì)自動(dòng)創(chuàng)建版本為1的該數(shù)據(jù)庫(kù)。
打開(kāi)數(shù)據(jù)庫(kù)的結(jié)果是,有可能觸發(fā)4種事件。
第一次打開(kāi)數(shù)據(jù)庫(kù)時(shí),會(huì)先觸發(fā)upgradeneeded事件,然后觸發(fā)success事件。
根據(jù)不同的需要,對(duì)上面4種事件設(shè)立回調(diào)函數(shù)。
上面代碼有兩個(gè)地方需要注意。首先,open方法返回的是一個(gè)對(duì)象(IDBOpenDBRequest),回調(diào)函數(shù)定義在這個(gè)對(duì)象上面。其次,回調(diào)函數(shù)接受一個(gè)事件對(duì)象event作為參數(shù),它的target.result屬性就指向打開(kāi)的IndexedDB數(shù)據(jù)庫(kù)。
獲得數(shù)據(jù)庫(kù)實(shí)例以后,就可以用實(shí)例對(duì)象的方法操作數(shù)據(jù)庫(kù)。
createObjectStore方法用于創(chuàng)建存放數(shù)據(jù)的“對(duì)象倉(cāng)庫(kù)”(object store),類似于傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)的表格。
上面代碼創(chuàng)建了一個(gè)名為firstOS的對(duì)象倉(cāng)庫(kù),如果該對(duì)象倉(cāng)庫(kù)已經(jīng)存在,就會(huì)拋出一個(gè)錯(cuò)誤。為了避免出錯(cuò),需要用到下文的objectStoreNames屬性,檢查已有哪些對(duì)象倉(cāng)庫(kù)。
createObjectStore方法還可以接受第二個(gè)對(duì)象參數(shù),用來(lái)設(shè)置“對(duì)象倉(cāng)庫(kù)”的屬性。
上面代碼中的keyPath屬性表示,所存入對(duì)象的email屬性用作每條記錄的鍵名(由于鍵名不能重復(fù),所以存入之前必須保證數(shù)據(jù)的email屬性值都是不一樣的),默認(rèn)值為null;autoIncrement屬性表示,是否使用自動(dòng)遞增的整數(shù)作為鍵名(第一個(gè)數(shù)據(jù)為1,第二個(gè)數(shù)據(jù)為2,以此類推),默認(rèn)為false。一般來(lái)說(shuō),keyPath和autoIncrement屬性只要使用一個(gè)就夠了,如果兩個(gè)同時(shí)使用,表示鍵名為遞增的整數(shù),且對(duì)象不得缺少指定屬性。
objectStoreNames屬性返回一個(gè)DOMStringList對(duì)象,里面包含了當(dāng)前數(shù)據(jù)庫(kù)所有“對(duì)象倉(cāng)庫(kù)”的名稱??梢允褂肈OMStringList對(duì)象的contains方法,檢查數(shù)據(jù)庫(kù)是否包含某個(gè)“對(duì)象倉(cāng)庫(kù)”。
上面代碼先判斷某個(gè)“對(duì)象倉(cāng)庫(kù)”是否存在,如果不存在就創(chuàng)建該對(duì)象倉(cāng)庫(kù)。
transaction方法用于創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)事務(wù)。向數(shù)據(jù)庫(kù)添加數(shù)據(jù)之前,必須先創(chuàng)建數(shù)據(jù)庫(kù)事務(wù)。
transaction方法接受兩個(gè)參數(shù):第一個(gè)參數(shù)是一個(gè)數(shù)組,里面是所涉及的對(duì)象倉(cāng)庫(kù),通常是只有一個(gè);第二個(gè)參數(shù)是一個(gè)表示操作類型的字符串。目前,操作類型只有兩種:readonly(只讀)和readwrite(讀寫)。添加數(shù)據(jù)使用readwrite,讀取數(shù)據(jù)使用readonly。
transaction方法返回一個(gè)事務(wù)對(duì)象,該對(duì)象的objectStore方法用于獲取指定的對(duì)象倉(cāng)庫(kù)。
transaction方法有三個(gè)事件,可以用來(lái)定義回調(diào)函數(shù)。
事務(wù)對(duì)象有以下方法,用于操作數(shù)據(jù)。
(1)添加數(shù)據(jù):add方法
獲取對(duì)象倉(cāng)庫(kù)以后,就可以用add方法往里面添加數(shù)據(jù)了。
add方法的第一個(gè)參數(shù)是所要添加的數(shù)據(jù),第二個(gè)參數(shù)是這條數(shù)據(jù)對(duì)應(yīng)的鍵名(key),上面代碼將對(duì)象o的鍵名設(shè)為1。如果在創(chuàng)建數(shù)據(jù)倉(cāng)庫(kù)時(shí),對(duì)鍵名做了設(shè)置,這里也可以不指定鍵名。
add方法是異步的,有自己的success和error事件,可以對(duì)這兩個(gè)事件指定回調(diào)函數(shù)。
(2)讀取數(shù)據(jù):get方法
讀取數(shù)據(jù)使用get方法,它的參數(shù)是數(shù)據(jù)的鍵名。
get方法也是異步的,會(huì)觸發(fā)自己的success和error事件,可以對(duì)它們指定回調(diào)函數(shù)。
從創(chuàng)建事務(wù)到讀取數(shù)據(jù),所有操作方法也可以寫成下面這樣鏈?zhǔn)叫问健?/p>
(3)更新記錄:put方法
put方法的用法與add方法相近。
(4)刪除記錄:delete方法
刪除記錄使用delete方法。
delete方法的參數(shù)是數(shù)據(jù)的鍵名。另外,delete也是一個(gè)異步操作,可以為它指定回調(diào)函數(shù)。
(5)遍歷數(shù)據(jù):openCursor方法
如果想要遍歷數(shù)據(jù),就要openCursor方法,它在當(dāng)前對(duì)象倉(cāng)庫(kù)里面建立一個(gè)讀取光標(biāo)(cursor)。
openCursor方法也是異步的,有自己的success和error事件,可以對(duì)它們指定回調(diào)函數(shù)。
回調(diào)函數(shù)接受一個(gè)事件對(duì)象作為參數(shù),該對(duì)象的target.result屬性指向當(dāng)前數(shù)據(jù)對(duì)象。當(dāng)前數(shù)據(jù)對(duì)象的key和value分別返回鍵名和鍵值(即實(shí)際存入的數(shù)據(jù))。continue方法將光標(biāo)移到下一個(gè)數(shù)據(jù)對(duì)象,如果當(dāng)前數(shù)據(jù)對(duì)象已經(jīng)是最后一個(gè)數(shù)據(jù)了,則光標(biāo)指向null。
openCursor方法還可以接受第二個(gè)參數(shù),表示遍歷方向,默認(rèn)值為next,其他可能的值為prev、nextunique和prevunique。后兩個(gè)值表示如果遇到重復(fù)值,會(huì)自動(dòng)跳過(guò)。
createIndex方法用于創(chuàng)建索引。
假定對(duì)象倉(cāng)庫(kù)中的數(shù)據(jù)對(duì)象都是下面person類型的。
可以指定這個(gè)數(shù)據(jù)對(duì)象的某個(gè)屬性來(lái)建立索引。
createIndex方法接受三個(gè)參數(shù),第一個(gè)是索引名稱,第二個(gè)是建立索引的屬性名,第三個(gè)是參數(shù)對(duì)象,用來(lái)設(shè)置索引特性。unique表示索引所在的屬性是否有唯一值,上面代碼表示name屬性不是唯一值,email屬性是唯一值。
有了索引以后,就可以針對(duì)索引所在的屬性讀取數(shù)據(jù)。index方法用于從對(duì)象倉(cāng)庫(kù)返回指定的索引。
var t = db.transaction(["people"],"readonly");
var store = t.objectStore("people");
var index = store.index("name");
var request = index.get(name);
上面代碼打開(kāi)對(duì)象倉(cāng)庫(kù)以后,先用index方法指定索引在name屬性上面,然后用get方法讀取某個(gè)name屬性所在的數(shù)據(jù)。如果沒(méi)有指定索引的那一行代碼,get方法只能按照鍵名讀取數(shù)據(jù),而不能按照name屬性讀取數(shù)據(jù)。需要注意的是,這時(shí)get方法有可能取回多個(gè)數(shù)據(jù)對(duì)象,因?yàn)閚ame屬性沒(méi)有唯一值。
另外,get是異步方法,讀取成功以后,只能在success事件的回調(diào)函數(shù)中處理數(shù)據(jù)。
索引的有用之處,還在于可以指定讀取數(shù)據(jù)的范圍。這需要用到瀏覽器原生的IDBKeyRange對(duì)象。
IDBKeyRange對(duì)象的作用是生成一個(gè)表示范圍的Range對(duì)象。生成方法有四種:
下面是一些代碼實(shí)例:
前三個(gè)方法(lowerBound、upperBound和bound)默認(rèn)包括端點(diǎn)值,可以傳入一個(gè)布爾值,修改這個(gè)屬性。
生成Range對(duì)象以后,將它作為參數(shù)輸入openCursor方法,就可以在所設(shè)定的范圍內(nèi)讀取數(shù)據(jù)。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: