indexedDB
相对于html5 中提到 web SQL Database,w3c已经明确声明放弃对其的继续支持,开始支持新的客户端数据库 indexedDB ,indexedDB 是一种noSQL 的数据库,并将利用 objectStore 来代替 传统数据库中 table 的概念。下面将通过代码来具体熟悉下 indexedDB 及其操作。
1、创建一个数据库。
//使浏览器都兼容 indexedDB,其实现在大多浏览器均以支持,包括360,QQ,FF,chrome 但是IE7-IE9;并不支持。
var indexedDB = window.indexedDB || window.webkitIndexDB || window.mozIndexedDB || window.msIndexedDB;
//创建一个数据库(打开一个数据库)
var request = indexedDB.open("admin",1);
//window.indexedDB.open(dbname,version), 我们通过这个方法创建了一个数据库(如果该数据库之前就存在,此操作则为打开一个数据库。) dbname :数据库的名称; version :数据库的版本号,该版本号在 初始化数据库是可选的,其默认值为 1;
2、相关的事件处理。
//indexedDB 中的相关操作是异步的,既是基于请求——响应的模式,因此这里会有一些简单的回调函数 onerror 、onsuccess 、 onupgradeneeded,我们将在IDBOpenDBRequest对象(request),上面调用这些方法
request = indexedDB.open("admin",2);
request.onupgradeneeded = function() {
alert('onupgradeneeded 事件被调用');
};
request.onsuccess = function() {
alert('onsuccess 事件被调用');
};
request.onerror = function() {
alert('onerror 事件被调用');
};
//函数的相关简单说明:onerror:当操作失败时(这里是创建数据库失败,或者是打开数据库失败,由于以后的操作中也会用到 onerror、onsuccess 事件,所以这里用"操作" ),onerror 事件将会被触发, onupgradeneeded:当创建一个数据库,或者是数据库版本更新时,会触发 onupgradeneeded 事件(在上例中,我们更新了 "admin" 数据库的版本号,所以 onupgradeneeded 事件会被触发),当然我们也可以在这里初始化我们的数据库信息, onsuccess : 当操作成功时,会触发onsuccess 事件。
3、相关的数据库处理
提及数据库的相关处理,当然就是简单的增、删、改、查了,不过在此之前,我们必须明确一些简单的概念。
objectStore : 由于 indexedDB 是noSQL的一种数据库,因此,他并没有传统数据库中 table的概念,但是他包含了 objectStore,可以帮助我们完成操作。对于 objectStore 我所理解的就是“对象商店”,当然就是用来储藏对象的喽,那对象不就是大家熟悉的 “{ }”嘛,而对象里面的当然就是要储存的数据啦。有过SQL数据库编程的童鞋可以将他理解成 table , 并且 objectStore 与 table 有一点是相同的,即一个数据库中可以有多个objectStore 。
键: 在这里的键值,我将它理解为 SQL数据库中的“主键”吧,但是在 objectStore 中 ,键有 2 种,其对储存对象的要求是不同的;下面对使用情况作简要的说明:
键类型 适用场景
不使用 任意值,但是每添加一条数据的时候需要指定键参数
Key Path 所储存的对象必须是 javascript 对象, 并且这个对象中必须 包含一个与 Key Path 值相同的属性。
Key Generator 所储存的对象可以包含任何类型的值,并且这个值会自增长,
Key Path/Key Generator 所储存的对象必须是 javascript 对象, 通常情况产生一个新键,并且产生的这个新键的值要与 KeyPath 的名字相同。如果对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性
事务:在indexedDB 中所有的操作都是基于事务来进行的,这里有些不同于SQL数据库的操作。
添加数据:
request.onsuccess = function(event) {
var db = event.target.result; //这里通过 event.target.result 来取得数据库对象(db)。
var objectStore = db.createObjectStore("books",{keyPath:"id"}); //------这里创建了一个数据对象,第一个参数为“数据商店”的名称,第二个参数为其键。
objectStore.createIndex("name","name",{unique:false}); //创建索引,便于以后的查找,第一个参数为索引名称(就是以数据对象中的某一个属性为索引),第二个参数为自定义的其值。unique 为约束,代表在数据对象中,其值必须是唯一的。
objectStore.createIndex("authorTel","authorTel",{unique:true});
objectStore.transaction.oncomplete = function(event) {
var bookStore = db.transaction(["books"],"readwrite").objectStore("books"); //这里表示在 books “的数据商店” 中,开启一个读写的事务,此外还有:read 只读;versionchange 版本更新
bookStore.add({id : 1, name : "Quarry Memrroes", author : "Fred", authorTel : "12345"});
bookStore.add({id : 2, name : "Water Buffaloes", author : "Fred", authorTel : "67890"});
bookStore.add({id : 3, name : "Bedrock Nights", author : "Barney", authorTel : "345678"});
};
};
获取数据:
基于主键检索:
request.onsuccess = function(event) {
var db = event.target.result;
var bookStore = db.transaction(["books"],"readwrite").objectStore("books"); //该操作如上,在 books “数据商店” 上,开启一个事务。
var fetch = bookStore.get(3); //这里是获取主键(这里就是 id)的那条数据对象,也可以理解成是一条记录吧!
fetch.onerror = function() { //这里 error 及下面的 success 函数, 和上面讲述的作用相同,不再赘述了。
alert("failed");
};
fetch.onsuccess = function() {
if(fetch.result) { // fetch.result 中,保存着我们所检索的那条数据对象,
alert(fetch.result.name); // 取得那个数据对象中的 name 属性值。
} else {
alert("Not found");
}
};
};
基于索引检索:
request.onsuccess = function(event) {
var db = event.target.result;
var index = db.transaction(["books"],"readwrite").objectStore("books").index('name'); //这里获取到相应的键名;
var fetch = index.get("Bedrock Nights");
fetch.onerror = function() {
alert("failed");
};
fetch.onsuccess = function() {
if(fetch.result) {
alert(fetch.result.id);
} else {
alert("Not found");
}
};
};
这两者的差别并不大,这里就不再赘述了。
更新数据:
request.onsuccess = function(event) {
var db = event.target.result;
var objectStore = db.transaction(["books"],"readwrite").objectStore("books"); //该操作如上,在 books “数据商店” 上,开启一个事务。
var fetch = objectStore.get(1); //首先先要获取到那条数据对象
fetch.onerror = function() {
alert("Failed");
};
fetch.onsuccess = function() {
var data = fetch.result;
data.name = "xxxxxxx"; //更新那条数据对象中指定属性的值
var requestUpdate = objectStore.put(data); //更改成功后,再将它重新加进去。
requestUpdate.onerror = function() {
alert("change Failed");
};
requestUpdate.onsuccess = function() {
alert("OK");
};
}
};
删除数据:
request.onsuccess = function(event) {
var db = event.target.result;
var objectStore = db.transaction(["books"],"readwrite").objectStore("books"); //该操作如上,在 books “数据商店” 上,开启一个事务。
var deleteObj = objectStore.delete(1); //删除 id 为 1 的那条数据对象
deleteObj.onerror = function() {
alert("failed");
};
deleteObj.onsuccess = function() {
alert("OK");
};
};
4、游标的使用:
当我们使用 get( ) 方法进行检索数据时,必须是要知道要查询的那个数据对象的一些信息的(比如上例中的 id、name),但是如果我们无法知道那些信息,但还是需要查询数据时,这时候我们就会用到“游标”,来帮助我们来遍历查询数据。下面是具体的示例:
简单使用游标查询:
request.onsuccess = function(event) {
var db = event.target.result,
var objectStore = db.transaction(["books"],"readwrite").objectStore("books"); //该操作如上,在 books “数据商店” 上,开启一个事务。
objectStore.openCursor().onsuccess = function(event) { //通过 openCursor() 方法,开启游标
var cursor = event.target.result;
if(cursor) {
alert(cursor.value.name); //这里 cursor.value 对象中,保存着我们的数据对象,有兴趣的话,可以打印出 cursor 具体查看( console.log(cursor) );
cursor.continue(); //使游标逐步的往下进行
} else {
alert("No more entries");
}
};
};
结合索引利用游标进行查询:
request.onsuccess = function(event) {
var db = event.target.result,
var index = db.transaction(["books"],"readwrite").objectStore("books").index("name");
index.openCursor().onsuccess = function(event) { //通过 openCursor() 方法,开启游标
var cursor = event.target.result;
if(cursor) {
alert(cursor.value.id);
cursor.continue(); //使游标逐步的往下进行
} else {
alert("No more entries");
}
};
};
这里的结合索引利用游标查询,即是两种方法的一种综合应用,并不具有新的意义,前面都已经讲过了,这里就不在详细说明了。
指明游标的方向和范围进行查询
游标范围:网上查了下讲的很好,直接就拿过来了。在这里附上链接吧,http://www.cnblogs.com/dolphinX/p/3416889.html
index.openCursor()/index.openKeyCursor()方法在不传递参数的时候会获取object store所有记录,像上面例子一样我们可以对搜索进行筛选
可以使用key range 限制游标中值的范围,把它作为第一个参数传给 openCursor() 或是 openKeyCursor()
IDBKeyRange.only(value):只获取指定数据
IDBKeyRange.lowerBound(value,isOpen):获取最小是value的数据,第二个参数用来指示是否排除value值本身,也就是数学中的是否是开区间
IDBKeyRange.upperBound(value,isOpen):和上面类似,用于获取最大值是value的数据
IDBKeyRange.bound(value1,value2,isOpen1,isOpen2):不用解释了吧
在这里PS下,关于JavaScript中字符比较的问题。。。附上链接 http://www.2cto.com/kf/201408/324339.html
游标方向:游标的方向默认当然是向下走的了。但是您也可以使用 prev 使他向前。 当然还有 nextunique,prevunique,其用于过滤数据对象中重复的数据。
request.onsuccess = function(event) {
var db = event.target.result;
var index = db.transaction(["books"],"readwrite").objectStore("books").index("name"); //这里必须要使用索引
var lowerBoundKeyRange = IDBKeyRange.lowerBound("Water Buffaloes",true);
index.openCursor(lowerBoundKeyRange).onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
alert(cursor.value.id);
cursor.continue();
}
}
};
这里要对.openCursor(range, direction ) 函数做简单的说明,第一个参数指定查询的范围,第二个参数指明查询的方向,如果只想指明查询方向,第一个参数可以设置为 null;
当使用完数据库后应该调用 db.close( ),及时的关闭数据库。
5、删除数据库:
request.onsuccess = function(event) {
indexedDB.deleteDatabase("admin"); //调用indexedDB.deleteDatabase(dbname); 用于删除数据库;
};
PS: indexedDB 是遵守同源策略的,意味着您不能跨域去操作这些信息。