首頁  >  文章  >  web前端  >  HTML5本機儲存-詳解IndexedDB的基本使用

HTML5本機儲存-詳解IndexedDB的基本使用

黄舟
黄舟原創
2017-03-21 15:02:311576瀏覽

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屬性中,

HTML5本機儲存-詳解IndexedDB的基本使用

這條指令請求的回應是一個IDBDatabase對象,這就是IndexedDB對象,

HTML5本機儲存-詳解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可以儲存的資料結構也有差異

键类型 存储数据
不使用 任意值,但是没添加一条数据的时候需要指定键参数
keyPath Javascript对象,对象必须有一属性作为键值
keyGenerator 任意值
都使用 Javascript对象,如果对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性


事务

在对新数据库做任何事情之前,需要开始一个事务。事务中需要指定该事务跨越哪些object store。

事务具有三种模式

  1. 只读:read,不能修改数据库数据,可以并发执行

  2. 读写:readwrite,可以进行读写操作

  3. 版本变更: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,&#39;students&#39;);
        },1000);

这样我们就在students object store里添加了三条记录,以id为键,在chrome控制台看看效果

HTML5本機儲存-詳解IndexedDB的基本使用

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(&#39;students&#39;)){
                    db.createObjectStore(&#39;students&#39;,{autoIncrement: true});
                }
                console.log(&#39;DB version changed to &#39;+version);
            };
        }

HTML5本機儲存-詳解IndexedDB的基本使用

剩下的两种方式有兴趣同学可以自己摸索一下了

查找数据

可以调用object store的get方法通过键获取数据,以使用keyPath做键为例

function getDataByKey(db,storeName,value){            
var transaction=db.transaction(storeName,&#39;readwrite&#39;); 
            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,&#39;readwrite&#39;); 
            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,&#39;readwrite&#39;); 
            var store=transaction.objectStore(storeName); 
            store.delete(value); 
        }

调用object store的clear方法可以清空object store

function clearObjectStore(db,storeName){            
var transaction=db.transaction(storeName,&#39;readwrite&#39;); 
            var store=transaction.objectStore(storeName); 
            store.clear();
}

调用数据库实例的deleteObjectStore方法可以删除一个object store,这个就得在onupgradeneeded里面调用了

if(db.objectStoreNames.contains(&#39;students&#39;)){ 
                    db.deleteObjectStore(&#39;students&#39;); 
}

最后

这就是关于indexedDB的基本使用方式,很多同学看了会觉得很鸡肋,和我们正常自己定义个对象使用没什么区别,也就是能保存在本地罢了,这是因为我们还没有介绍indexedDB之所以称为indexed的杀器——索引,这个才是让indexedDB大显神通的东西,下篇我们就来看看这个杀器。

以上是HTML5本機儲存-詳解IndexedDB的基本使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn