IndexedDB(一:基本使用)
在HTML5本地存儲——Web SQL Database提到過Web SQL Database實際上已經被廢棄,而HTML5的支持的本地存儲實際上變成了
Web Storage(Local Storage和Session Storage)與IndexedDB。Web Storage使用簡單字符串鍵值對在本地存儲數據,方便靈活,但是對於大量結構化數據存儲力不從心,IndexedDB是為了能夠在客戶端存儲大量的結構化數據,並且使用索引高效檢索的API。
異步API
在IndexedDB大部分操作並不是我們常用的調用方法,返回結果的模式,而是請求——響應的模式,比如打開數據庫的操作
var request=window.indexedDB.open(‘testDB‘);
這條指令並不會返回一個DB對象的句柄,我們得到的是一個IDBOpenDBRequest對象,而我們希望得到的DB對象在其result屬性中,
這條指令請求的響應是一個 IDBDatabase對象,這就是IndexedDB對象,
除了result,IDBOpenDBRequest接口定義了幾個重要屬性
● onerror: 請求失敗的回調函數句柄
● onsuccess:請求成功的回調函數句柄
● onupgradeneeded:請求數據庫版本變化句柄
所謂異步API是指並不是這條指令執行完畢,我們就可以使用request.result來獲取indexedDB對象了,就像使用ajax一樣,語句執行完並不代表已經獲取到了對象,所以我們一般在其回調函數中處理。
創建數據庫
剛才的語句已經展示了如何打開一個indexedDB數據庫,調用indexedDB.open方法就可以創建或者打開一個indexedDB。看一個完整的處理
function openDB (name) { var request=window.indexedDB.open(name); request.onerror=function(e){ console.log(‘OPen Error!‘); }; request.onsuccess=function(e){ myDB.db=e.target.result; }; } var myDB={ name:‘test‘, version:1, db:null }; openDB(myDB.name);
代碼中定義了一個myDB對象,在創建indexedDB request的成功毀掉函數中,把request獲取的DB對象賦值給了myDB的db屬性,這樣就可以使用myDB.db來訪問創建的indexedDB了。
version
我們註意到除了onerror和onsuccess,IDBOpenDBRequest還有一個類似回調函數句柄——onupgradeneeded。這個句柄在我們請求打開的數據庫的版本號和已經存在的數據庫版本號不一致的時候調用。
indexedDB.open()方法還有第二個可選參數,數據庫版本號,數據庫創建的時候默認版本號為1,當我們傳入的版本號和數據庫當前版本號不一致的時候onupgradeneeded就會被調用,當然我們不能試圖打開比當前數據庫版本低的version,否則調用的就是onerror了,修改一下剛才例子
function openDB (name,version) {
var version=version || 1;
var request=window.indexedDB.open(name,version);
request.onerror=function(e){
console.log(e.currentTarget.error.message);
};
request.onsuccess=function(e){
myDB.db=e.target.result;
};
request.onupgradeneeded=function(e){
console.log(‘DB version changed to ‘+version);
};
}
var myDB={
name:‘test‘,
version:3,
db:null
};
openDB(myDB.name,myDB.version);
由於剛才已經創建了版本為1的數據庫,打開版本為3的時候,會在控制臺輸出:DB version changed to 3
關閉與刪除數據庫
關閉數據庫可以直接調用數據庫對象的close方法
function closeDB(db){
db.close();
}
刪除數據庫使用indexedDB對象的deleteDatabase方法
function deleteDB(name){
indexedDB.deleteDatabase(name);
}
簡單調用
var myDB={
name:‘test‘,
version:3,
db:null
};
openDB(myDB.name,myDB.version);
setTimeout(function(){
closeDB(myDB.db);
deleteDB(myDB.name);
},500);
由於異步API願意,不能保證能夠在closeDB方法調用前獲取db對象(實際上獲取db對象也比執行一條語句慢得多),所以用了setTimeout延遲了一下。當然我們註意到每個indexedDB實例都有onclose回調函數句柄,用以數據庫關閉的時候處理,有興趣同學可以試試,原理很簡單,不演示了。
object store
有了數據庫後我們自然希望創建一個表用來存儲數據,但indexedDB中沒有表的概念,而是objectStore,一個數據庫中可以包含多個objectStore,objectStore是一個靈活的數據結構,可以存放多種類型數據。也就是說一個objectStore相當於一張表,裏面存儲的每條數據和一個鍵相關聯。
我們可以使用每條記錄中的某個指定字段作為鍵值(keyPath),也可以使用自動生成的遞增數字作為鍵值(keyGenerator),也可以不指定。選擇鍵的類型不同,objectStore可以存儲的數據結構也有差異
事務
在對新數據庫做任何事情之前,需要開始一個事務。事務中需要指定該事務跨越哪些object store。
事務具有三種模式
- 只讀:read,不能修改數據庫數據,可以並發執行
- 讀寫:readwrite,可以進行讀寫操作
- 版本變更:verionchange
var transaction=db.transaction([students‘,‘taecher‘]); //打開一個事務,使用students 和teacher object store
var objectStore=transaction.objectStore(‘students‘); //獲取students object store
給object store添加數據
調用數據庫實例的createObjectStore方法可以創建object store,方法有兩個參數:store name和鍵類型。調用store的add方法添加數據。有了上面知識,我們可以向object store內添加數據了
keyPath
因為對新數據的操作都需要在transaction中進行,而transaction又要求指定object store,所以我們只能在創建數據庫的時候初始化object store以供後面使用,這正是onupgradeneeded的一個重要作用,修改一下之前代碼
function openDB (name,version) {
var version=version || 1;
var request=window.indexedDB.open(name,version);
request.onerror=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);
};
}
這樣在創建數據庫的時候我們就為其添加了一個名為students的object store,準備一些數據以供添加
var students=[{
id:1001,
name:"Byron",
age:24
},{
id:1002,
name:"Frank",
age:30
},{
id:1003,
name:"Aaron",
age:26
}];
function addData(db,storeName){
var transaction=db.transaction(storeName,‘readwrite‘);
var store=transaction.objectStore(storeName);
for(var i=0;i<students.length;i++){
store.add(students[i]);
}
}
openDB(myDB.name,myDB.version);
setTimeout(function(){
addData(myDB.db,‘students‘);
},1000);
這樣我們就在students object store裏添加了三條記錄,以id為鍵,在chrome控制臺看看效果
keyGenerate
function openDB (name,version) {
var version=version || 1;
var request=window.indexedDB.open(name,version);
request.onerror=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);
};
}
剩下的兩種方式有興趣同學可以自己摸索一下了
查找數據
可以調用object store的get方法通過鍵獲取數據,以使用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);
};
}
更新數據
可以調用object store的put方法更新數據,會自動替換鍵值相同的記錄,達到更新目的,沒有相同的則添加,以使用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);
};
}
刪除數據及object store
調用object store的delete方法根據鍵值刪除記錄
function deleteDataByKey(db,storeName,value){
var transaction=db.transaction(storeName,‘readwrite‘);
var store=transaction.objectStore(storeName);
store.delete(value);
}
調用object store的clear方法可以清空object store
function clearObjectStore(db,storeName){
var transaction=db.transaction(storeName,‘readwrite‘);
var store=transaction.objectStore(storeName);
store.clear();
}
調用數據庫實例的deleteObjectStore方法可以刪除一個object store,這個就得在onupgradeneeded裏面調用了
if(db.objectStoreNames.contains(‘students‘)){
db.deleteObjectStore(‘students‘);
}
最後
這就是關於indexedDB的基本使用方式,很多同學看了會覺得很雞肋,和我們正常自己定義個對象使用沒什麽區別,也就是能保存在本地罷了,這是因為我們還沒有介紹indexedDB之所以稱為indexed的殺器——索引,這個才是讓indexedDB大顯神通的東西,下篇我們就來看看這個殺器。
IndexedDB(一:基本使用)