在HTML5本地存儲——Web SQL Database提到過Web SQL Database實際上已經被廢棄,而HTML5的支持的本地存儲實際上變成了 Web Storage(Local Storage和Session Storage)與IndexedDB。Web Storage使用簡單字符串鍵值對在本地存儲數據,方便靈活,可是對於大量結構化數據存儲力不從心,IndexedDB是爲了可以在客戶端存儲大量的結構化數據,而且使用索引高效檢索的API。ajax
在IndexedDB大部分操做並非咱們經常使用的調用方法,返回結果的模式,而是請求——響應的模式,好比打開數據庫的操做chrome
var request=window.indexedDB.open('testDB');
複製代碼
這條指令並不會返回一個DB對象的句柄,咱們獲得的是一個IDBOpenDBRequest對象,而咱們但願獲得的DB對象在其result屬性中, 數據庫
除了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了。函數
咱們注意到除了onerror和onsuccess,IDBOpenDBRequest還有一個相似回調函數句柄——onupgradeneeded。這個句柄在咱們請求打開的數據庫的版本號和已經存在的數據庫版本號不一致的時候調用。 indexedDB.open()方法還有第二個可選參數,數據庫版本號,數據庫建立的時候默認版本號爲1,當咱們傳入的版本號和數據庫當前版本號不一致的時候onupgradeneeded就會被調用,固然咱們不能試圖打開比當前數據庫版本低的version,不然調用的就是onerror了,修改一下剛纔例子spa
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 3code
關閉數據庫能夠直接調用數據庫對象的close方法cdn
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回調函數句柄,用以數據庫關閉的時候處理,有興趣同窗能夠試試,原理很簡單,不演示了。
有了數據庫後咱們天然但願建立一個表用來存儲數據,但indexedDB中沒有表的概念,而是objectStore,一個數據庫中能夠包含多個objectStore,objectStore是一個靈活的數據結構,能夠存放多種類型數據。也就是說一個objectStore至關於一張表,裏面存儲的每條數據和一個鍵相關聯。
咱們可使用每條記錄中的某個指定字段做爲鍵值(keyPath),也可使用自動生成的遞增數字做爲鍵值(keyGenerator),也能夠不指定。選擇鍵的類型不一樣,objectStore能夠存儲的數據結構也有差別
在對新數據庫作任何事情以前,須要開始一個事務。事務中須要指定該事務跨越哪些object store。 事務具備三種模式
var transaction=db.transaction([students','taecher']); //打開一個事務,使用students 和teacher object store
var objectStore=transaction.objectStore('students'); //獲取students object store
複製代碼
調用數據庫實例的createObjectStore方法能夠建立object store,方法有兩個參數:store name和鍵類型。調用store的add方法添加數據。有了上面知識,咱們能夠向object store內添加數據了
由於對新數據的操做都須要在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控制檯看看效果
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的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大顯神通的東西,下篇咱們就來看看這個殺器。