引用文档:
HTML5本地存储——IndexedDB(一:基本使用)
HTML5本地存储——IndexedDB(二:索引)
IndexedDB API
JavaScript高级程序设计(第三版)
IndexedDB简介:
IndexedDB是在浏览器中保存结构化数据的一种数据库,IndexedDB的思想是创建一套API,方便保存和读取JavaScript对象,同时支持查询和搜索。IndexedDB的最大特色是使用对象保存数据。一个IndexedDB数据库,就是一组位于相同命名空间下的对象的集合。
IndexedDB打开数据库:
-
open
IndexedDB是一个作为API宿主的全局对象,由于IndexedDB设计的操作为异步进行,所以大多数的操作为请求操作,打开数据库即向数据库发送open
请求,如下代码所示,发送请求后,如果数据库存在,就打开该数据库,如果数据库不存在,就创建并打开该数据库,打开该数据库成功后会返回一个IDBOpenDBRequest
对象,这个对象上可以添加一系列的处理程序,如代码中的onerror
事件和onsuccess
事件,在onsuccess
中可以得到IDBDatabase
对象。
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
var request,database;
request = indexedDB.open('test');
request.onerror = function(e){
console.log(e.target.errorCode);
};
request.onsuccess = function(e){
database = e.target.result;
console.log('创建或打开数据库成功') ;
}
以上代码在控制台中得到结果如下图所示:
-
version
默认情况下,IndexedDB是没有版本号的,最好一开始为数据库指定一个版本号,我们可以在创建或者打开数据库时为其指定版本号,在上述代码中将open函数传入的参数更改为request = indexedDB.open('test',1);
这样就为当前数据库设定了版本号,通过设置版本号可以知道想使用的数据库是否设置了合适的对象存储空间,在整个Web应用中,随着数据库的更新和修改,可能会产生很多个不同的版本号(ps:关于版本号的用途也没有摸索特别清楚,可以确定的是每次增加对象存储空间都是要修改版本号的。)
IndexedDB对象存储空间:
在建立或者打开数据库后,我们一般的操作是建立表,向表中插入数据,在IndexedDB中,用对象存储空间ObjectStore
来代替表的概念,存储空间中的对象就相当于表中插入的数据。在上一步打开数据库的onsuccess
中我们可以获得到IDBDatabase
对象,创建存储空间就是在通过该对象调用createObjectStore
函数。
var data=[{
id:1007,
name:"Byron",
age:24
},{
id:1008,
name:"Frank",
age:30
},{
id:1009,
name:"Aaron",
age:26
}];
var store = database.createObjectStore("students",{keyPath:"id"});
//var store = database.createObjectStore("students",{autoIncrement:true});
for(var i = 0 ; i < data.length;i++){
request = store.add(data[i]);
request.onerror = function(){
console.error('数据库中已有该数据')
};
request.onsuccess = function(){
console.log('数据已存入数据库')
};
}
上述代码中createObjectStore
第一个参数为存储对象空间的名字,第二个参数为存储空间的键,既数据库表中的主键,我们进行查找或者删除某个对象都要通过这个键来查找,如果不设置存储空间的键,可以如代码注释行一样,设置自增类型。
API文档中对于该参数说明如下:
在浏览器中显示如下:
- 错误说明
在创建存储对象空间可能报如下错误:
Failed to execute 'createObjectStore' on 'IDBDatabase': The database is not running a version change transaction.
报该错误的原因是:第一次open
的success
事件处于version_change
事务中 这个时候不能createObjectStore
,createObjectStore
操作要在onupgradeneeded
的事件中执行。
为对象存储空间添加数据:
创建存储空间之后,可以用add()或者put()方法为其添加数据,这两个方法都接收所要保存的对象,区别之处在于,使用add()方法,遇到键值相同的对象会返回错误,而put()则不会报错,会重写原有对象。如下代码使用add()方法进行数据添加,代码中包括打开数据库及创建存储对象空间。可在控制台中直接运行。
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
var request,database;
var data=[{
id:1007,
name:"Byron",
age:24
},{
id:1008,
name:"Frank",
age:30
},{
id:1009,
name:"Aaron",
age:26
}];
request = indexedDB.open('test',1);
request.onerror = function(){
console.log('error');
};
request.onsuccess = function(e){
database = e.target.result;
console.log('创建或打开数据库成功') ;
};
request.onupgradeneeded=function(e){
database = e.target.result;
if(!database.objectStoreNames.contains("students")){
var store = database.createObjectStore("students",{autoIncrement:true});
for(var i = 0 ; i < data.length;i++){
request = store.add(data[i]);
request.onerror = function(){
console.error('数据库中已有该数据')
};
request.onsuccess = function(){
console.log('数据已存入数据库')
};
}
}
}
事务
创建对象存储空间之后,数据库中的增删改查都是通过事务transaction
来完成的,在数据库对象上调用transaction()
方法可以创建事务。
var transaction= database.transaction("students",'readwrite');
transaction.objectStore("students")
如上代码保证只加载students
存储空间的数据,然后通过事务访问该空间,对该空间中的数据进行操作,transaction()中传入的第二个参数为对该空间操作的方式,默认为readonly
只读操作,代码中传入的是readwrite
读写操作。其它可访问MDN APIIDBTransaction
完整代码:
该demo可在控制台中执行函数,由于IndexedDB API的异步进行,如果所有函数同时执行,打印出来的信息会不按说明排列,建议想测试哪个功能在控制台中执行即可。默认功能为建立打开数据库、创建存储空间添加数据。
demo默认执行图示
demo在控制台中完整执行图示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="author" content="sina_mobile">
<meta name="format-detection" content="telephone=no" />
<title></title>
</head>
<body>
<script>
var myDB={
name:'univisity',
version:1,
db:null,
ojstore:{
name:'students',//存储空间表的名字
keypath:'id'//主键
}
};
var INDEXDB = {
indexedDB:window.indexedDB||window.webkitindexedDB,
IDBKeyRange:window.IDBKeyRange || window.webkitIDBKeyRange,//键范围
openDB:function(dbname,dbversion,callback){
//建立或打开数据库,建立对象存储空间(ObjectStore)
var self = this;
var version = dbversion || 1;
var request = self.indexedDB.open(dbname,version);
request.onerror = function(e){
console.log(e.currentTarget.error.message);
};
request.onsuccess = function(e){
myDB.db = e.target.result;
console.log('成功建立并打开数据库:'+myDB.name+' version'+dbversion);
};
request.onupgradeneeded=function(e){
var db=e.target.result,transaction= e.target.transaction,store;
if(!db.objectStoreNames.contains(myDB.ojstore.name)){
//没有该对象空间时创建该对象空间
store = db.createObjectStore(myDB.ojstore.name,{keyPath:myDB.ojstore.keypath});
console.log('成功建立对象存储空间:'+myDB.ojstore.name);
}
}
},
deletedb:function(dbname){
//删除数据库
var self = this;
self.indexedDB.deleteDatabase(dbname);
console.log(dbname+'数据库已删除')
},
closeDB:function(db){
//关闭数据库
db.close();
console.log('数据库已关闭')
},
addData:function(db,storename,data){
//添加数据,重复添加会报错
var store = store = db.transaction(storename,'readwrite').objectStore(storename),request;
for(var i = 0 ; i < data.length;i++){
request = store.add(data[i]);
request.onerror = function(){
console.error('add添加数据库中已有该数据')
};
request.onsuccess = function(){
console.log('add添加数据已存入数据库')
};
}
},
putData:function(db,storename,data){
//添加数据,重复添加会更新原有数据
var store = store = db.transaction(storename,'readwrite').objectStore(storename),request;
for(var i = 0 ; i < data.length;i++){
request = store.put(data[i]);
request.onerror = function(){
console.error('put添加数据库中已有该数据')
};
request.onsuccess = function(){
console.log('put添加数据已存入数据库')
};
}
},
getDataByKey:function(db,storename,key){
//根据存储空间的键找到对应数据
var store = db.transaction(storename,'readwrite').objectStore(storename);
var request = store.get(key);
request.onerror = function(){
console.error('getDataByKey error');
};
request.onsuccess = function(e){
var result = e.target.result;
console.log('查找数据成功')
console.log(result);
};
},
deleteData:function(db,storename,key){
//删除某一条记录
var store = store = db.transaction(storename,'readwrite').objectStore(storename);
store.delete(key)
console.log('已删除存储空间'+storename+'中'+key+'记录');
},
clearData:function(db,storename){
//删除存储空间全部记录
var store = db.transaction(storename,'readwrite').objectStore(storename);
store.clear();
console.log('已删除存储空间'+storename+'全部记录');
}
}
var students=[{
id:1001,
name:"Byron",
age:24
},{
id:1002,
name:"Frank",
age:30
},{
id:1003,
name:"Aaron",
age:26
}];
INDEXDB.openDB(myDB.name,myDB.version);
setTimeout(function(){
console.log('****************添加数据****************************');
INDEXDB.addData(myDB.db,myDB.ojstore.name,students);
// console.log('******************add重复添加**************************');
// INDEXDB.addData(myDB.db,myDB.ojstore.name,students);
// console.log('*******************put重复添加*************************');
// INDEXDB.putData(myDB.db,myDB.ojstore.name,students);
// console.log('*******************获取数据1001*************************');
// INDEXDB.getDataByKey(myDB.db,myDB.ojstore.name,1001);
// console.log('******************删除数据1001************');
// INDEXDB.deleteData(myDB.db,myDB.ojstore.name,1001);
// console.log('******************删除全部数据************');
// INDEXDB.clearData(myDB.db,myDB.ojstore.name);
// console.log('******************关闭数据库************');
// INDEXDB.closeDB(myDB.db);
// console.log('******************删除数据库************');
// INDEXDB.deletedb(myDB.name);
},800)
</script>
</body>
</html>