HTML5 的一个重要特性是本地数据持久性,它使用户能够在线和离线访问 Web 应用程序。IndexedDB支持本地存储大量对象,并使用健壮的数据访问机制检索数据。与 Web Storage 相比,IndexedDB 具有多个优势,其中包括索引、事务处理和健壮的查询功能。一个网站能够创建多个本地数据库,其中每个数据库都可以存放多个数据对象,一个对象中有存在多个数据集合,每个数据集合中有多个键值对。我们接下来一起学习一下关于IndexedDB的一些使用方法,包括数据的增删改查,以及索引和游标的使用方法。

创建数据库

首先我们创建一个名为testDB的数据库,之后我们的操作都是在这个数据库里面进行。open()可接受两个参数,一个为数据库名称,一个为数据库版本号,如果数据库不存在则创建。

var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
//创建一个数据库
function createDb(){    
    var res=window.indexedDB.open('testDB');
    res.onerror=function(e){
        alert("Database error:"+e.target.errorCode);
    };
    res.onsuccess=function(event){
        alert("Database Create!");
    };
}

删除数据库

//删除数据库
function deleteDataBase(){    
    var deleteDb=window.indexedDB.deleteDatabase("testDB");
    deleteDb.onsuccess=function(e){
        alert("deleteDb success!");
    }
    deleteDb.onerror=function(e){
        alert("deleteDb error:"+e.target.errorCode);
    }
}

创建一个版本不同的数据库

这里有三个函数,onerror在打开或者创建数据库失败的时候执行,onsuccess在数据打开或者创建成功的时候执行,onupgradeneeded在数据库版本改变的时候执行。

//创建一个与版本号为2的数据库
function CreateVersion(){    
    var res=window.indexedDB.open('testDB',2);
    res.onerror=function(e){
        alert("Database error:"+e.target.errorCode);
    };
    res.onsuccess=function(e){
        alert("Database Create!");
    };
    res.onupgradeneeded=function(e){
        alert("Database Version Changed!")
    }
}

创建一个存储对象

在这里我们创建了一个名称为students的存储对象,并且在创建的时候指定id字段作为数据存储的键值。

function createObjStore(){    
    var res=indexedDB.open('testDB',3);
    res.onupgradeneeded=function(e){        
        var db=e.target.result;        
        if(!db.objectStoreNames.contains('students')){
            db.createObjectStore('students',{keyPath:"id"});
        }
        alert('DB version changed');
    };
}// createDb();// createObjStore();

增加数据

写了一个增加数据的函数,obj表示你的数据需要存储在那个存储对象中,dbname数据库名称,version数据库版本号,data要存放的数据。

function addData(obj,dbname,version,data){    
    var res =indexedDB.open(dbname,version);
    res.onsuccess = function (evt) {        
        var db = evt.target.result;        //使用事务
        var store =db.transaction(obj, "readwrite").objectStore(obj);
        store.add(data);
    }
}

写到这里的时候遇到了一个错误”未捕获TypeError:无法使用indexeddb读取null的属性transaction”,关于这个错误的发生,是由于不了解异步javascript,而indexedDB就是异步的,可以参考以下这篇文章。

Uncaught TypeError: Cannot read property ‘transaction’ of null with an indexeddb

https://stackoverflow.com/questions/24256202/uncaught-typeerror-cannot-read-property-transaction-of-null-with-an-indexeddb

删除数据

//删除
function deleteData(storeName){    
        var req=window.indexedDB.open("testDB");
        req.onsuccess=function(e){        
            var db=e.target.result;        
            //删除id为100的学生信息
            var res=db.transaction(storeName,"readwrite").objectStore(storeName).delete("100");
            res.onsuccess=function(){            
            console.log("delete success");
            }
        }
}//deleteData("students");

更新数据

function updateData(storeName){    
        var req=window.indexedDB.open("testDB");
        req.onsuccess=function(e){        
            var db=e.target.result;        
            var store=db.transaction(storeName,"readwrite").objectStore(storeName);        
            //更新id为100的学生信息
            store.get("100").onsuccess=function(evt){           
                var student=evt.target.result;
                student.name="newtest";            
                var res=store.put(student);
                res.onsuccess=function(){                
                    console.log("success");
            }
        }
    }
}//updateData("students");

创建索引

在创建索引的时候会出现创建不成功情况,索引的创建需要在创建存储对象的时候进行创建,如果先创建了存储对象,然后通过获取到对象,再进行索引创建的时候,这样是不成功的,所以在这里我们重新创建了一个名称teachers的存储对象。在这里创建了三个索引’nameIndex’,’idIndex’,’ageIndex’,其中将idIndex的属性设置唯一。

//创建索引
function createIndex(){    
    var req=window.indexedDB.open('testDB',7);
    req.onsuccess=function(e){        
        console.log("success");
    }
    req.onupgradeneeded=function(e){        
        var db=e.target.result;        
        var store=db.createObjectStore("teachers",{keyPath:"id"});        
        //创建索引
        store.createIndex('nameIndex','name',{unique:false});
        store.createIndex('idIndex','id',{unique:true});
        store.createIndex("ageIndex","age",{unique:false});
    }    
}
//createIndex();//var data={"id":"0","name":"teacher0","age":"20"};

//addData("teachers","testDB",7,data);

索引查询

//根据索引查询
function findByIndex(obj,db){    
    var req=window.indexedDB.open("testDB");
    req.onsuccess=function(e){        
        var db=e.target.result;        
        var store=db.transaction(obj).objectStore(obj);        
        var index=store.index("nameIndex");                
        //查询名字为“teacher0”的老师信息
        index.get("teacher0").onsuccess=function(e){            
            var teacher=e.target.result;            
            console.log(teacher);
        }
    }
}//findByIndex("teachers","testDB");

游标

在这里我们利用游标来遍历数据库中存放的所有数据。

//游标
function findByCursor(stoeName){    
        var req=window.indexedDB.open("testDB");
        req.onsuccess=function(e){        
        var db=e.target.result;        
        var store=db.transaction(stoeName).objectStore(stoeName);       
        //打开游标
        var res=store.openCursor();
        res.onsuccess=function(evt){            
        var cursor=evt.target.result;            
        if(cursor){                
            console.log(cursor.key,cursor.value);
                cursor.continue();
            }
        }
    }
}
// var data={"id":"1","name":"teacher1","age":"21"};/
/ addData("teachers","testDB",7,data);// findByCursor("teachers");

索引和游标

利用索引和游标查询了名称叫做”teacher1“的所有老师信息。

//索引和游标的结合
function findByIndexAndCursor(storeName){
        var req=window.indexedDB.open("testDB");
        req.onsuccess=function(e){
        var db=e.target.result;        
        var store=db.transaction(storeName).objectStore(storeName);        
        var index=store.index("nameIndex");        //打开游标
        var res=index.openCursor(IDBKeyRange.only('teacher1'));
        res.onsuccess=function(evt){            
        var cursor=evt.target.result;            
        if(cursor){                
        console.log(cursor.key,cursor.value);
                cursor.continue();
            }
        }
    }
}
// var data={"id":"2","name":"teacher1","age":"23"};
// addData("teachers","testDB",7,data);// findByIndexAndCursor("teachers");

参考文档:

HTML5本地存储——IndexedDB
http://www.cnblogs.com/dolphinX/p/3415761.html
使用 HTML5 IndexedDB API
https://www.ibm.com/developerworks/cn/web/wa-indexeddb/
Uncaught TypeError: Cannot read property ‘transaction’ of null with an indexeddb
https://stackoverflow.com/questions/24256202/uncaught-typeerror-cannot-read-property-transaction-of-null-with-an-indexeddb

查看完整代码

http://git.oschina.net/kuaidy/H5XueXiBiJi/blob/master/indexeddb.html