前面說過html5對于離線應用的支持是很好的,不禁支持localstorage這樣在客戶端存儲一個鍵值對的方式而且還可以引用manifest文件,將需要緩存的文件在其中定義,其實html5中還可以使用indexdb,又稱索引數據庫,該數據庫可以用來存儲離線對象。下面開始:
請求完成后的回調
所有的請求完成之后都會有一個回調,onsuccess 和onerror,其中:onsuccess表示請求成功時候的回調,onerror 表示請求失敗時候的回調。同時還可以使用javascript中的 try/catch來捕獲異常,在進一步的處理。
使用數據庫
一個數據庫一次只能有一個版本,初次創建改數據庫的時候版本號是0,當我們需要更改已經創建好的數據庫時候,就需要更改其版本號,當更改 版本號的時候,會觸發upgradeneeded回調,所以修改數據庫或者存儲對象的方法必須放到upgradeneeded方法中執行。
判斷當前瀏覽器是否支持indexdb
if (!window.indexedDB) { window.alert("您的瀏覽器不支持indexdb"); }<!--這里indexDB是window對象的屬性,類似于alert所以window可以省略-->
創建數據庫
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript"> function createDatabase(indexDbName) { //調用 open 方法并傳遞數據庫名稱。如果不存在具有指定名稱的數據庫,則會創建該數據庫 var openRequest = indexedDB.open(indexDbName); var db; openRequest.onerror = function(e) {//當創建數據庫失敗時候的回調 console.log("Database error: " + e.target.errorCode); }; openRequest.onsuccess = function(event) { console.log("Database created"); db = openRequest.result;//創建數據庫成功時候,將結果給db,此時db就是當前數據庫 //alert("this is :"+db); }; openRequest.onupgradeneeded = function (evt) {//更改數據庫,或者存儲對象時候在這里處理 }; } </script></head><body> <a href="javascript:createDatabase('firstdb')">createDatabase</a></body></html>
上面這段代碼可以創建一個數據庫到客戶端。
刪除數據庫
通過調用 deleteDatabase 方法,并且傳入需要刪除的數據庫名稱來刪除現有數據庫。
function deleteDatabase(indexDbName) { var deleteDbRequest = indexedDB.deleteDatabase(indexDbName); deleteDbRequest.onsuccess = function (event) { console.log("detete database success"); }; deleteDbRequest.onerror = function (e) { console.log("Database error: " + e.target.errorCode); }; }
存儲數據
objectstore
在indexdb中沒有表的概念,而是使用objectstore來存儲對象的,一個數據庫中可以包含多個objectStore,objectStore是一個靈活的數據結構,可以存放多種類型數據。我們可以使用每條記錄中的某個指定字段作為鍵值(keyPath),也可以使用自動生成的遞增數字作為鍵值(keyGenerator),也可以不指定。選擇鍵的類型不同,objectStore可以存儲的數據結構也有差異
事物
在更新數據庫內容或者插入新的數據時候,需要首先開啟到事物,并且需要制定當前事物操作了那些objectstore。
事務具有三種模式
-
只讀:read,不能修改數據庫數據,可以并發執行
-
讀寫:readwrite,可以進行讀寫操作
-
版本變更:verionchange
因為對新數據的操作都需要在transaction中進行,而transaction又要求指定object store,所以我們只能在創建數據庫的時候初始化object store以供后面使用。
指定keyid添加數據
指定keyid,可以理解為指定一個主鍵
//添加數據 function insertAnObj(indexDbName) { var userinfos=[{ id:1001, name:"小李", age:24 },{ id:1002, name:"老王", age:30 },{ id:1003, name:"王麻子", age:26 }]; var openRequest = indexedDB.open(indexDbName,1); openRequest.onerror = function(e) {//當創建數據庫失敗時候的回調 console.log("Database error: " + e.target.errorCode); }; openRequest.onsuccess = function(event) { console.log("Database created"); db = openRequest.result; //創建數據庫成功時候,將結果給db,此時db就是當前數據庫 //alert("this is :"+db); //打開和userinfo相關的objectstore的事物 var transaction = db.transaction("userinfo",'readwrite'); var store=transaction.objectStore("userinfo"); for(var i=0;i<userinfos.length;i++){ //alert("add"+userinfos[i]); store.add(userinfos[i]);//將對象添加至userinfo相關的objectstore中 } }; openRequest.onupgradeneeded = function(event) { var db = event.target.result; //在第一次創建數據庫的時候,就創建userinfo相關的objectstore,以供后面添加數據時候使用 if(!db.objectStoreNames.contains('userinfo')){ //keyPath:Javascript對象,對象必須有一屬性作為鍵值 db.createObjectStore('userinfo',{keyPath:"id"}); } } }
使用autoIncrement添加數據
指定autoIncrement,可以理解為指定了一個主鍵自動增長。
//指定主鍵自動增長 function insertAutoInc(indexDbName) { var userinfos=[{ id:1001, name:"小李", age:24 },{ id:1002, name:"老王", age:30 },{ id:1003, name:"王麻子", age:26 }]; var openRequest = indexedDB.open(indexDbName,2); openRequest.onerror = function(e) {//當創建數據庫失敗時候的回調 console.log("Database error: " + e.target.errorCode); }; openRequest.onsuccess = function(event) { console.log("Database created"); db = openRequest.result; //創建數據庫成功時候,將結果給db,此時db就是當前數據庫 //alert("this is :"+db); //打開和userinfo相關的objectstore的事物 var transaction = db.transaction("userinfo",'readwrite'); var store=transaction.objectStore("userinfo"); for(var i=0;i<userinfos.length;i++){ //alert("add"+userinfos[i]); store.add(userinfos[i]);//將對象添加至userinfo相關的objectstore中 } }; openRequest.onupgradeneeded = function(event) { var db = event.target.result; //在第一次創建數據庫的時候,就創建userinfo相關的objectstore,以供后面添加數據時候使用 if(!db.objectStoreNames.contains('userinfo')){ //keyPath:Javascript對象,對象必須有一屬性作為鍵值 db.createObjectStore('userinfo',{autoIncrement: true}); } } }
查找數據
根據id查找數據
之前我們已經添加過了定義key為autoincreament類型方式的數據,現在就可以根據id來查找單條數據了。
function findDbdata(indexDbName,value) { var openRequest = indexedDB.open(indexDbName); var db; openRequest.onerror = function(e) {//當創建數據庫失敗時候的回調 console.log("Database error: " + e.target.errorCode); }; openRequest.onsuccess = function(event) { console.log("Database created"); db = openRequest.result; //創建數據庫成功時候,將結果給db,此時db就是當前數據庫 var transaction = db.transaction("userinfo",'readwrite'); var objectStore = transaction.objectStore("userinfo"); //var cursor = objectStore.openCursor(); var request = objectStore.get(Number(1));//查找i=1的對象,這里使用Number將1轉換成數值類型 request.onsuccess = function(e) { var res = e.target.result; //查找成功時候返回的結果對象 console.dir(res); if (res) { for (var field in res) { //遍歷每一個對象屬性 console.log(field+":"+res[field]); // alert(res[field]); }; }; } }; openRequest.onupgradeneeded = function (event) {//更改數據庫,或者存儲對象時候在這里處理 }; }
查找所有數據
function findAllDbdata(indexDbName) { var openRequest = indexedDB.open(indexDbName); var db; openRequest.onsuccess = function(event) { console.log("Database created"); db = openRequest.result; //創建數據庫成功時候,將結果給db,此時db就是當前數據庫 var transaction = db.transaction("userinfo",'readonly'); var objectStore = transaction.objectStore("userinfo"); var cursor = objectStore.openCursor(); cursor.onsuccess = function(e) { var res = e.target.result; if(res) { console.log("Key", res.key); var request = objectStore.get(Number(res.key));//根據查找出來的id,再次逐個查找 request.onsuccess = function(e) { var res = e.target.result; //查找成功時候返回的結果對象 //console.dir(res); if (res) { for (var field in res) { //遍歷每一個對象屬性 console.log(field+":"+res[field]); // alert(res[field]); }; }; } res.continue(); } } }; }
根據id刪除數據
刪除跟新增一樣,需要創建事務,然后調用刪除接口delete來刪除數據
function deleteDataById(indexDbName) { var openRequest = indexedDB.open(indexDbName); var db; openRequest.onsuccess = function(event) { db = openRequest.result; //創建數據庫成功時候,將結果給db,此時db就是當前數據庫 var transaction = db.transaction("userinfo",'readwrite'); var objectStore = transaction.objectStore("userinfo"); var request = objectStore.delete(Number(2));//根據查找出來的id,再次逐個查找 request.onsuccess = function(e) { console.log("delete success"); } } }
刪除所有數據
通過objectstore.clear()刪除所有的數據。
function deleteAllData(indexDbName) { var openRequest = indexedDB.open(indexDbName); var db; openRequest.onsuccess = function(event) { db = openRequest.result; //創建數據庫成功時候,將結果給db,此時db就是當前數據庫 var transaction = db.transaction("userinfo",'readwrite'); var objectStore = transaction.objectStore("userinfo"); objectStore.clear(); } }
創建索引
我們可以在創建object store的時候指明索引,使用object store的createIndex創建索引,方法有三個參數
-
索引名稱
-
索引屬性字段名
-
索引屬性值是否唯一
這里我新創建一個數據庫,并且設置基于name和age的索引:
//指定主鍵自動增長 function insertAutoInc(indexDbName) { var userinfos=[{ id:1001, name:"小李", age:24 },{ id:1002, name:"老王", age:30 },{ id:1003, name:"王麻子", age:26 }]; var openRequest = indexedDB.open(indexDbName,2); openRequest.onerror = function(e) {//當創建數據庫失敗時候的回調 console.log("Database error: " + e.target.errorCode); }; openRequest.onsuccess = function(event) { console.log("Database created"); db = openRequest.result; //創建數據庫成功時候,將結果給db,此時db就是當前數據庫 //alert("this is :"+db); //打開和userinfo相關的objectstore的事物 var transaction = db.transaction("userinfo",'readwrite'); var store=transaction.objectStore("userinfo"); for(var i=0;i<userinfos.length;i++){ //alert("add"+userinfos[i]); store.add(userinfos[i]);//將對象添加至userinfo相關的objectstore中 } }; openRequest.onupgradeneeded = function(event) { var db = event.target.result; //在第一次創建數據庫的時候,就創建userinfo相關的objectstore,以供后面添加數據時候使用 if(!db.objectStoreNames.contains('userinfo')){ //keyPath:Javascript對象,對象必須有一屬性作為鍵值 var objectStore = db.createObjectStore('userinfo',{autoIncrement: true}); objectStore.createIndex('nameIndex','name',{unique:true});//這里假定名字不能重復,創建基于name的唯一索引 objectStore.createIndex('ageIndex','age',{unique:false});//創建基于age的索引 } } }
利用索引查詢數據
可以利用索引快速獲取數據,name的索引是唯一的沒問題,但是對于age索引只會取到第一個匹配值,要想得到所有age符合條件的值就需要使用游標了
function getDataByIndex(indexDbName) { var openRequest = indexedDB.open(indexDbName); var db; openRequest.onerror = function(e) {//當創建數據庫失敗時候的回調 console.log("Database error: " + e.target.errorCode); }; openRequest.onsuccess = function(event) { console.log("Database created"); db = openRequest.result; //創建數據庫成功時候,將結果給db,此時db就是當前數據庫 var transaction = db.transaction("userinfo",'readwrite'); var objectStore = transaction.objectStore("userinfo"); var nameIndex = objectStore.index("nameIndex"); //獲得nameIndex索引 nameIndex.get("小李").onsuccess = function(e) { //根據name索引獲得數據成功的回調 var userinfo = e.target.result; console.log("id:"+userinfo.id+"==name:"+userinfo.name+"==age:"+userinfo.age); } } }
游標和索引結合使用
剛才我們不僅創建了一個name的唯一索引,而且還創建了一個age的索引,如果我們根據age來獲取數據,有可能會有多條,由于age不唯一,所以這個時候就需要使用游標來遍歷數據。這里我先插入兩條age=24的記錄。
function getDataByAgeIndex(indexDbName) { var openRequest = indexedDB.open(indexDbName); var db; openRequest.onerror = function(e) {//當創建數據庫失敗時候的回調 console.log("Database error: " + e.target.errorCode); }; openRequest.onsuccess = function(event) { console.log("Database created"); db = openRequest.result; //創建數據庫成功時候,將結果給db,此時db就是當前數據庫 var transaction = db.transaction("userinfo",'readwrite'); var objectStore = transaction.objectStore("userinfo"); var nameIndex = objectStore.index("ageIndex"); //獲得ageIndex索引 var request = nameIndex.openCursor();//openCursor沒有參數的時候,表示獲得所有數據 request.onsuccess = function(e) {//openCursor成功的時候回調該方法 var cursor = e.target.result; if (cursor) {//循環遍歷cursor var userinfo = cursor.value; //alert(userinfo.name); console.log("id:"+userinfo.id+"==name:"+userinfo.name+"==age:"+userinfo.age); cursor.continue(); }; } } }
同時可以在opencursor的時候傳入key range,來限制范圍。
IDBKeyRange.only(value):只獲取指定數據
IDBKeyRange.lowerBound(value,isOpen):獲取最小是value的數據,第二個參數用來指示是否排除value值本身,也就是數學中的是否是開區間
IDBKeyRange.upperBound(value,isOpen):和上面類似,用于獲取最大值是value的數據
IDBKeyRange.bound(value1,value2,isOpen1,isOpen2):表示在value1和value2之間,是否包含value1和value2
這里為了演示方便,我先刪除之前的數據庫,重新插入更多的數據,現在所有數據如下:
IDBKeyRange.only(value)
這里只需要在上面opencursor的時候將該限制條件傳入即可,其他代碼將保持不變,如下:
var request = nameIndex.openCursor(IDBKeyRange.only(Number(24)));
這里只根據age索引查詢age==24的所有數據。
IDBKeyRange.lowerBound(value,isOpen)
在使用IDBKeyRange.lowerBound(28,true)來獲取年齡大于28的并且包含28歲的所有數據。
var request = nameIndex.openCursor(IDBKeyRange.lowerBound(Number(28),true));
ok,今天就到這里了,希望大家喜歡。