在HTML5本地存储——Web SQL Database提到过Web SQL Database实际上已经被废弃,而HTML5的支持的本地存储实际上变成了ajax
Web Storage(Local Storage和Session Storage)与IndexedDB。Web Storage使用简单字符串键值对在本地存储数据,方便灵活,可是对于大量结构化数据存储力不从心,IndexedDB是为了可以在客户端存储大量的结构化数据,而且使用索引高效检索的API。chrome
异步API
在IndexedDB大部分操做并非咱们经常使用的调用方法,返回结果的模式,而是请求——响应的模式,好比打开数据库的操做数据库
var request=window.indexedDB.open('testDB');
这条指令并不会返回一个DB对象的句柄,咱们获得的是一个IDBOpenDBRequest对象,而咱们但愿获得的DB对象在其result属性中,数据结构
这条指令请求的响应是一个 IDBDatabase对象,这就是IndexedDB对象,并发
除了result,IDBOpenDBRequest接口定义了几个重要属性异步
- onerror: 请求失败的回调函数句柄
- onsuccess:请求成功的回调函数句柄
- onupgradeneeded:请求数据库版本变化句柄
所谓异步API是指并非这条指令执行完毕,咱们就可使用request.result来获取indexedDB对象了,就像使用ajax同样,语句执行完并不表明已经获取到了对象,因此咱们通常在其回调函数中处理。函数
建立数据库
刚才的语句已经展现了如何打开一个indexedDB数据库,调用indexedDB.open方法就能够建立或者打开一个indexedDB。看一个完整的处理post
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了。spa
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。
事务具备三种模式
- 只读:read,不能修改数据库数据,能够并发执行
- 读写:readwrite,能够进行读写操做
- 版本变动: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,'students'); },1000);
这样咱们就在students object store里添加了三条记录,以id为键,在chrome控制台看看效果
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('students')){ db.createObjectStore('students',{autoIncrement: true}); } console.log('DB version changed to '+version); }; }
剩下的两种方式有兴趣同窗能够本身摸索一下了
查找数据
能够调用object store的get方法经过键获取数据,以使用keyPath作键为例
function getDataByKey(db,storeName,value){ var transaction=db.transaction(storeName,'readwrite'); 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,'readwrite'); 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,'readwrite'); var store=transaction.objectStore(storeName); store.delete(value); }
调用object store的clear方法能够清空object store
function clearObjectStore(db,storeName){ var transaction=db.transaction(storeName,'readwrite'); var store=transaction.objectStore(storeName); store.clear(); }
调用数据库实例的deleteObjectStore方法能够删除一个object store,这个就得在onupgradeneeded里面调用了
if(db.objectStoreNames.contains('students')){ db.deleteObjectStore('students'); }
最后
这就是关于indexedDB的基本使用方式,不少同窗看了会以为很鸡肋,和咱们正常本身定义个对象使用没什么区别,也就是能保存在本地罢了,这是由于咱们尚未介绍indexedDB之因此称为indexed的杀器——索引,这个才是让indexedDB大显神通的东西,下篇咱们就来看看这个杀器。