HTML5 API详解(18):IndexedDB 本地存储
Web SQL Database實(shí)際上已經(jīng)被廢棄,而HTML5的支持的本地存儲(chǔ)實(shí)際上變成了Local Storage和Session Storage與IndexedDB。Web Storage使用簡(jiǎn)單字符串鍵值對(duì)在本地存儲(chǔ)數(shù)據(jù),方便靈活,但是對(duì)于大量結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)力不從心,IndexedDB是為了能夠在客戶端存儲(chǔ)大量的結(jié)構(gòu)化數(shù)據(jù),并且使用索引高效檢索的API。
異步API
在IndexedDB大部分操作并不是我們常用的調(diào)用方法,返回結(jié)果的模式,而是請(qǐng)求——響應(yīng)的模式,比如打開數(shù)據(jù)庫(kù)的操作
var request=window.indexedDB.open('testDB');這條指令并不會(huì)返回一個(gè)DB對(duì)象的句柄,我們得到的是一個(gè)IDBOpenDBRequest對(duì)象,而我們希望得到的DB對(duì)象在其result屬性中,
這條指令請(qǐng)求的響應(yīng)是一個(gè) IDBDatabase對(duì)象,這就是IndexedDB對(duì)象,
除了result,IDBOpenDBRequest接口定義了幾個(gè)重要屬性
onerror: 請(qǐng)求失敗的回調(diào)函數(shù)句柄
onsuccess:請(qǐng)求成功的回調(diào)函數(shù)句柄
onupgradeneeded:請(qǐng)求數(shù)據(jù)庫(kù)版本變化句
創(chuàng)建數(shù)據(jù)庫(kù)
剛才的語(yǔ)句已經(jīng)展示了如何打開一個(gè)indexedDB數(shù)據(jù)庫(kù),調(diào)用indexedDB.open方法就可以創(chuàng)建或者打開一個(gè)indexedDB??匆粋€(gè)完整的處理
代碼中定義了一個(gè)myDB對(duì)象,在創(chuàng)建indexedDB request的成功毀掉函數(shù)中,把request獲取的DB對(duì)象賦值給了myDB的db屬性,這樣就可以使用myDB.db來(lái)訪問創(chuàng)建的indexedDB了。
version
我們注意到除了onerror和onsuccess,IDBOpenDBRequest還有一個(gè)類似回調(diào)函數(shù)句柄——onupgradeneeded。這個(gè)句柄在我們請(qǐng)求打開的數(shù)據(jù)庫(kù)的版本號(hào)和已經(jīng)存在的數(shù)據(jù)庫(kù)版本號(hào)不一致的時(shí)候調(diào)用。
indexedDB.open()方法還有第二個(gè)可選參數(shù),數(shù)據(jù)庫(kù)版本號(hào),數(shù)據(jù)庫(kù)創(chuàng)建的時(shí)候默認(rèn)版本號(hào)為1,當(dāng)我們傳入的版本號(hào)和數(shù)據(jù)庫(kù)當(dāng)前版本號(hào)不一致的時(shí)候onupgradeneeded就會(huì)被調(diào)用,當(dāng)然我們不能試圖打開比當(dāng)前數(shù)據(jù)庫(kù)版本低的version,否則調(diào)用的就是onerror了,修改一下剛才例子
由于剛才已經(jīng)創(chuàng)建了版本為1的數(shù)據(jù)庫(kù),打開版本為3的時(shí)候,會(huì)在控制臺(tái)輸出:DB version changed to 3
關(guān)閉與刪除數(shù)據(jù)庫(kù)
關(guān)閉數(shù)據(jù)庫(kù)可以直接調(diào)用數(shù)據(jù)庫(kù)對(duì)象的close方法
function closeDB(db){db.close();}刪除數(shù)據(jù)庫(kù)使用indexedDB對(duì)象的deleteDatabase方法
function deleteDB(name){indexedDB.deleteDatabase(name);}簡(jiǎn)單調(diào)用
var myDB={name:'test',version:3,db:null};openDB(myDB.name,myDB.version);setTimeout(function(){closeDB(myDB.db);deleteDB(myDB.name);},500);由于異步API愿意,不能保證能夠在closeDB方法調(diào)用前獲取db對(duì)象(實(shí)際上獲取db對(duì)象也比執(zhí)行一條語(yǔ)句慢得多),所以用了setTimeout延遲了一下。當(dāng)然我們注意到每個(gè)indexedDB實(shí)例都有onclose回調(diào)函數(shù)句柄,用以數(shù)據(jù)庫(kù)關(guān)閉的時(shí)候處理,有興趣同學(xué)可以試試,原理很簡(jiǎn)單,不演示了。
object store
有了數(shù)據(jù)庫(kù)后我們自然希望創(chuàng)建一個(gè)表用來(lái)存儲(chǔ)數(shù)據(jù),但indexedDB中沒有表的概念,而是objectStore,一個(gè)數(shù)據(jù)庫(kù)中可以包含多個(gè)objectStore,objectStore是一個(gè)靈活的數(shù)據(jù)結(jié)構(gòu),可以存放多種類型數(shù)據(jù)。也就是說(shuō)一個(gè)objectStore相當(dāng)于一張表,里面存儲(chǔ)的每條數(shù)據(jù)和一個(gè)鍵相關(guān)聯(lián)。
我們可以使用每條記錄中的某個(gè)指定字段作為鍵值(keyPath),也可以使用自動(dòng)生成的遞增數(shù)字作為鍵值(keyGenerator),也可以不指定。選擇鍵的類型不同,objectStore可以存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)也有差異
| 鍵類型 | 存儲(chǔ)數(shù)據(jù) |
| 不使用 | 任意值,但是沒添加一條數(shù)據(jù)的時(shí)候需要指定鍵參數(shù) |
| keyPath | Javascript對(duì)象,對(duì)象必須有一屬性作為鍵值 |
| keyGenerator | 任意值 |
| 都使用 | Javascript對(duì)象,如果對(duì)象中有keyPath指定的屬性則不生成新的鍵值,如果沒有自動(dòng)生成遞增鍵值,填充keyPath指定屬性 |
事務(wù)
在對(duì)新數(shù)據(jù)庫(kù)做任何事情之前,需要開始一個(gè)事務(wù)。事務(wù)中需要指定該事務(wù)跨越哪些object store。
事務(wù)具有三種模式
只讀:read,不能修改數(shù)據(jù)庫(kù)數(shù)據(jù),可以并發(fā)執(zhí)行
讀寫:readwrite,可以進(jìn)行讀寫操作
版本變更:verionchange
var transaction=db.transaction([students','taecher']); //打開一個(gè)事務(wù),使用students 和teacher object store var objectStore=transaction.objectStore('students'); //獲取students object store
給object store添加數(shù)據(jù)
調(diào)用數(shù)據(jù)庫(kù)實(shí)例的createObjectStore方法可以創(chuàng)建object store,方法有兩個(gè)參數(shù):store name和鍵類型。調(diào)用store的add方法添加數(shù)據(jù)。有了上面知識(shí),我們可以向object store內(nèi)添加數(shù)據(jù)了
keyPath
因?yàn)閷?duì)新數(shù)據(jù)的操作都需要在transaction中進(jìn)行,而transaction又要求指定object store,所以我們只能在創(chuàng)建數(shù)據(jù)庫(kù)的時(shí)候初始化object store以供后面使用,這正是onupgradeneeded的一個(gè)重要作用,修改一下之前代碼
function openDB (name,version) {var version=version || 1;var request=window.indexedDB.open(name,version);request.οnerrοr=function(e){console.log(e.currentTarget.error.message);};request.onsuccess=function(e){myDB.db=e.target.result;};request.onupgradeneeded=function(e){var db=e.target.result;if(!db.objectStoreNames.contains('students')){db.createObjectStore('students',{keyPath:"id"});}console.log('DB version changed to '+version);};}
這樣在創(chuàng)建數(shù)據(jù)庫(kù)的時(shí)候我們就為其添加了一個(gè)名為students的object store,準(zhǔn)備一些數(shù)據(jù)以供添加
var students=[{ id:1001, name:"Byron", age:24 },{ id:1002, name:"Frank", age:30 },{ id:1003, name:"Aaron", age:26 }];這樣我們就在students object store里添加了三條記錄,以id為鍵,在chrome控制臺(tái)看看效果
keyGenerate
function openDB (name,version) {var version=version || 1;var request=window.indexedDB.open(name,version);request.οnerrοr=function(e){console.log(e.currentTarget.error.message);};request.onsuccess=function(e){myDB.db=e.target.result;};request.onupgradeneeded=function(e){var db=e.target.result;if(!db.objectStoreNames.contains('students')){db.createObjectStore('students',{autoIncrement: true});}console.log('DB version changed to '+version);};}剩下的兩種方式有興趣同學(xué)可以自己摸索一下了
查找數(shù)據(jù)
可以調(diào)用object store的get方法通過(guò)鍵獲取數(shù)據(jù),以使用keyPath做鍵為例
function getDataByKey(db,storeName,value){var transaction=db.transaction(storeName,'readwrite'); var store=transaction.objectStore(storeName); var request=store.get(value); request.onsuccess=function(e){ var student=e.target.result; console.log(student.name); }; }更新數(shù)據(jù)
可以調(diào)用object store的put方法更新數(shù)據(jù),會(huì)自動(dòng)替換鍵值相同的記錄,達(dá)到更新目的,沒有相同的則添加,以使用keyPath做鍵為例
function updateDataByKey(db,storeName,value){var transaction=db.transaction(storeName,'readwrite'); var store=transaction.objectStore(storeName); var request=store.get(value); request.onsuccess=function(e){ var student=e.target.result; student.age=35;store.put(student); }; }刪除數(shù)據(jù)及object store
調(diào)用object store的delete方法根據(jù)鍵值刪除記錄
function deleteDataByKey(db,storeName,value){var transaction=db.transaction(storeName,'readwrite'); var store=transaction.objectStore(storeName); store.delete(value); }調(diào)用object store的clear方法可以清空object store
function clearObjectStore(db,storeName){var transaction=db.transaction(storeName,'readwrite'); var store=transaction.objectStore(storeName); store.clear(); }調(diào)用數(shù)據(jù)庫(kù)實(shí)例的deleteObjectStore方法可以刪除一個(gè)object store,這個(gè)就得在onupgradeneeded里面調(diào)用了
if(db.objectStoreNames.contains('students')){ db.deleteObjectStore('students'); }總結(jié)
以上是生活随笔為你收集整理的HTML5 API详解(18):IndexedDB 本地存储的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 科大星云诗社动态20201208
- 下一篇: 地址已在使用 java_java – U