IndexedDB教程

1、简介

现有的浏览器数据储存方案,都不适合储存大量数据:Cookie 的大小不超过4KB;LocalStorage 在 2.5MB 到 10MB 之间(各家浏览器不同),而且不提供搜索功能,不能建立自定义的索引。所以,需要一种新的解决方案,这就是 IndexedDB 诞生的背景

IndexedDB有以下几个特点
(1)键值对储存: IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
(2)异步: IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
(3)支持事务: IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
(4)同源限制: IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
(5)储存空间大: IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。
(6)支持二进制储存: IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。

2、基本概念

名称 属性 描述
数据库 IDBDatabase 对象 数据库是一系列相关数据的容器。每个域名(严格的说,是协议 + 域名 + 端口)都可以新建任意多个数据库。IndexedDB 数据库有版本的概念。同一个时刻,只能有一个版本的数据库存在。如果要修改数据库结构(新增或删除表、索引或者主键),只能通过升级数据库版本完成。
对象仓库 IDBObjectStore 对象 每个数据库包含若干个对象仓库(object store)。它类似于关系型数据库的表格。
索引 IDBIndex 对象 为了加速数据的检索,可以在对象仓库里面,为不同的属性建立索引。
事务 IDBTransaction 对象 在对新数据库做任何事情之前,需要开始一个事务。事务中需要指定该事务跨越哪些object store。事务有3种模式:1)只读 : read;2) 读写:readwrite;3)版本变更:verionchange
操作请求 IDBRequest 对象
指针 IDBCursor 对象
主键集合 IDBKeyRange 对象

3、基本方法

3.1、打开数据库

/*
* @param String dataBaseName 数据库的名字
* @param Number version 数据库版本号,如果省略,在打开已有数据库时,默认为当前版本号,新建数据库时,默认为1.
*/
var request = window.indexedDB.open(dataBaseName, version);

indexedDB.open() 方法返回一个IDBRequest 对象。这个对象通过error 、success、upgradeneeded三个事件,处理打开数据库的操作结果。
(1)error事件:表示打开数据库失败。

request.onerror = function(event){
	console.log('数据库打开失败');
}

(2)success事件:表示成功打开数据库

var db;
request.onsuccess = function(event){
	db = request.result;
	console.log('数据库打开成功');
}

(3)upgradeneeded事件:新建数据库或者当指定的版本号大于数据库实际版本号,就会发生数据库升级事件,此时会调用upgradeneeded事件。

var db;
request.onupgradeneeded = function(event){
	db = event.target.result;
	var objectStore;
	//判断class表格是否存在
	if (!db.objectStoreNames.contains('class')){
	//创建一个叫class的表格,主键是id
		ojbectStore = db.createObjectStore('class',{keyPath:'id'});
	}
}

如果数据记录里面没有合适作为主键的属性,那么可以让IndexedDB自动生成主键。
代码如下:

//创建一个objectStore名字叫class,指定主键为一个递增的整数。
var objectStore = db.createObjectStore('class',{autoIncrement:true});

新建对象仓库以后,下一步可以新建索引

/*
* @param name 索引名称
* @param proto 索引所在的属性
* @param object 配置对象,说明该属性是否包含重复的值
*/
IDBObject.createIndex(name,proto,object);
var db;
request.onupgradeneeded = function(event){
	db = event.target.result;
	var objectStore;
	if (!db.objectStoreNames.contains('class')){
		ojbectStore = db.createObjectStore('class',{keyPath:'id'});
	}
	//新建索引
	objectStore.createIndex('name', 'name', {unique : false});
	objectStore.createIndex('email',  'email', {unique : true});
}

4、接下来用一个例子来讲解吧

var testIDB = {
	name : 'class',
	version : 1,
	db : null
}
/*
*@param name 数据库名称
*@param version 版本号
*/
function openIDB (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){
         testIDB.db=e.target.result;
     };
     request.onupgradeneeded=function(e){
     	var db=e.target.result;
     	if(!db.objectStoreNames.contains('classOne')){
        	db.createObjectStore('classOne',{keyPath:"id"});
     	}
        console.log('DB version changed to '+version);
    };
}
//准备一些数据
var students = [
	{id:1,name:'sai',age:28,height:189,weight:65},
	{id:2,name:'zhang',age:22,height:140,weight:44},
	{id:3,name:'yao',age:26,height:150,weight:74}
];
/*
*添加数据到数据库
*@param Array db
*@param String storeName
*@param Array data
*/
function addData(db,storeName,data){
	//打开一个事务
    var transaction=db.transaction(storeName,'readwrite'); 
    //获取objectStore
    var store=transaction.objectStore(storeName); 
    for(var i=0; i < data.length; i++){
    //往objectStore添加数据
        store.add(data[i]);
    }
}
openIDB(testIDB.name,testIDB.version);
//由于异步API原因,不能保证能够在addData方法调用前获取db对象(实际上获取db对象也比执行一条语句慢得多),所以此处用了延时。
setTimeout(function(){
    addData(testIDB.db, 'classOne', students);
},1000);

执行上述代码后查看结果

/*
*查找数据
*@param Array db
*@param String storeName
*@param String value
*/
function getData(db,storeName,value){
	//打开一个事务
    var transaction = db.transaction(storeName,'readwrite'); 
    //获取objectStore
    var store = transaction.objectStore(storeName); 
    //通过get方法获取数据
    var request=store.get(value); 
    request.onsuccess=function(e){ 
        var student=e.target.result; 
        console.log(student); 
    };
}
getData(testIDB.db,'classOne',1);
//{id: 1, name: "sai", age: 28, height: 189, weight: 65}

/*
*更新数据
*@param Array db
*@param String storeName
*@param String keyPath
*@param String updateValue
*/
function updateDataByKey(db, storeName, keyPath, updateValue){
	//打开一个事务
    var transaction = db.transaction(storeName,'readwrite'); 
    //获取objectStore
    var store = transaction.objectStore(storeName); 
    var request = store.get(keyPath); 
    request.onsuccess = function(e){ 
        var student = e.target.result; 
        student.age = updateValue;
        store.put(student); 
    };
}
//更新classOne表格id=1的age数据为222
updateDataByKey(testIDB.db,'classOne',1,222);
getData(testIDB.db,'classOne',1);
//{id: 1, name: "sai", age: 222, height: 189, weight: 65}
/*
*按照keyPath删除数据
*@param Array db
*@param String storeName
*@param String keyPath
*/
function deleteDataByKey(db,storeName,keyPath){
	//打开一个事务
    var transaction = db.transaction(storeName,'readwrite'); 
    //获取objectStore
    var store = transaction.objectStore(storeName); 
    //按照keyPath值删除数据
    store.delete(keyPath); 
}
//删除名字为classOne的storeObject里keyPath为1的数据
deleteDataByKey(testIDB.db, 'classOne', 1);
/*
*清空objectStore里面所有数据
*@param Array db
*@param String storeName
*/
function clearObjectStore(db,storeName){
	//打开一个事务
    var transaction=db.transaction(storeName,'readwrite'); 
    //获取objectStore
    var store=transaction.objectStore(storeName); 
    //清空classOne表格里所有数据
    store.clear();
}
//清空classOne里面所有数据
clearObjectStore(testIDB.db,'classOne');

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

//删除classOne表格
if (db.objectStoreNames.contains('classOne')){
	db.deleteObjectStore('classOne'); 
}

5、索引

function openIDB (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){
         testIDB.db=e.target.result;
     };
     request.onupgradeneeded=function(e){
     	var db=e.target.result;
     	if(!db.objectStoreNames.contains('classOne')){
        	var store = db.createObjectStore('classOne',{keyPath:"id"});
        	/*
			*创建索引
			*@param nameIndex 索引名称
			*@param name 索引属性字段名
			*@param Object 索引属性值是否唯一
			*/
        	store.createIndex('nameIndex','name',{unique:true}); 
            store.createIndex('ageIndex','age',{unique:false});
     	}
     	console.log('DB version changed to '+version);
    };
}

添加索引后的效果

此处需要刷新才会出来效果哦

猜你喜欢

转载自blog.csdn.net/z1324402468/article/details/86664165