您的位置:首页 > 数据库

IndexedDB浏览器中的数据库详细介绍。(H5)

2017-11-10 11:57 393 查看

IndexedDB介绍:

IndexedDB是在浏览器中保存结构化数据的一种数据库。替代目前已被废弃的Web SQL Database API而出现的,IndexedDB设计的操作完全是异步进行的。因此,大多数操作会以请求方式进行,但这些操作会在后期执行,然后如果成功则返回结果。差不多每一次IndexedDB操作,都需要你注册onerror或onsuccess事件处理程序,以确保适当地处理结果。

Indexed将是一个作为API宿主的全局对象。

首先第一步是要打开它indexeDB.open();

如果传入的数据库已经存在,就会发送一个打开它的请求;如果传入的数据的数据库不存在,就会发送一个创建并打开它的请求。执行如下代码


var request = indexedDB.open("admin");
console.log(request);


效果如下



调用indexDB.open();返回了一个IDBOpenDBRequest对象,可以看到这个对象上的onerror、onsuccess、onupgradeneeded事件都为空,result显示的是创建成功了的IndexDB数据库的实例,但是这个实例我们要取到的话,只能在onsuccess事件中,测试代码

var db;
var request = indexedDB.open("admin");
request.onsuccess = function() {
db = event.target.result;
console.log(db);
}


效果如下:



从图中,我们可以看到我们创建的数据库实例,名字为admin,objectStoreNames是这个数据库中的储存空间的名字,里面为空,后面会解释这个,版本默认设置了1

对象储存空间

即上面的objectStoreNames中的内容,这个空间中是我们储存数据的地方,如何向数据库中创建这个存储空间,这就要在onupgradeneeded事件中进行,但是要触发这个事件,就是要更新数据库的版本号,新打开的版本号要大于默认版本号,测试代码如下

var db;
var request = indexedDB.open("admin",2);
request.onsuccess = function() {
db = event.target.result;
}
var users = [
{
username: "007",
firstName: "James",
lastName: "Bond",
password: "foo"
},
{
username: "ace",
firstName: "John",
lastName: "Smith",
password: "bar"
},
{
username: "foobar",
firstName: "Michael",
lastName: "Johnson",
password: "secret"
}
];
request.onupgradeneeded = function() {
var store = db.createObjectStore("users",{keyPath:"username"});
for (var i = 0;i < users.length;i++) {
store.add(users[i]);
}

d3d6
console.log(store);
}


效果如下:





从这两张图可以看出我们在名为admin的数据库中创建了users的储存空间,分别储存了三个对象,第一张图中,可以看到indexName为空,这个是索引,是我们之后要介绍的内容,这里先知道下,keyPath是键值,用对象中的username,以便我们查询,添加之类操作获取对象的通行证,当然前面的索引也是对这个的一个加强,我们默认会设置一个键,但是可以利用索引再创建其他副键,以便方便数据库操作,后面会做介绍,我们还可以看到name为”users”,transaction是事务,基本来说我们后续的操作都要围绕事务来进行,下面我们来说事务。

事务

在数据库对象上调用transaction()方法可以创建事务。任何时候,只要想读取或修改数据,都要通过事务来组织所有操作。


代码如下

var db;
var request = indexedDB.open("admin",2);
request.onsuccess = function() {
db = event.target.result;
}
var users = [
{
username: "007",
firstName: "James",
lastName: "Bond",
password: "foo"
},
{
username: "ace",
firstName: "John",
lastName: "Smith",
password: "bar"
},
{
username: "foobar",
firstName: "Michael",
lastName: "Johnson",
password: "secret"
}
];
request.onupgradeneeded = function() {
var store = db.createObjectStore("users",{keyPath:"username"});
for (var i = 0;i < users.length;i++) {
store.add(users[i]);
}
console.log(store);
}
//事务相关的操作
//跟据键值获取对象
function getData() {
var transaction = db.transaction("users",'readwrite');
var store = transaction.objectStore("users");
var request = store.get("007");
request.onsuccess = function(event) {
var result = event.target.result;
console.log(result.firstName);
};
}
//因为这里要调用onsucess时候保存的db的实例,但是因为异步操作,如果不用超时调用,可能db还没有获取到!
setTimeout(function() {
getData();
},500);


结果



我将操作都一次性写出来

var db;
var request = indexedDB.open("admin",2);
request.onsuccess = function() {
db = event.target.result;
}
var users = [
{
username: "007",
firstName: "James",
lastName: "Bond",
password: "foo"
},
{
username: "ace",
firstName: "John",
lastName: "Smith",
password: "bar"
},
{
username: "foobar",
firstName: "Michael",
lastName: "Johnson",
password: "secret"
}
];
request.onupgradeneeded = function() {
var store = db.createObjectStore("users",{keyPath:"username"});
for (var i = 0;i < users.length;i++) {
store.add(users[i]);
}
console.log(store);
}
//事务相关的操作
//跟据键值获取对象
function getData() {
var transaction = db.transaction("users",'readwrite');
var store = transaction.objectStore("users");
var request = store.get("007");
request.onsuccess = function(event) {
var result = event.target.result;
console.log(result.firstName);
};
}
//更新
function updataData() {
var transaction = db.transaction('users','readwrite');
var store = transaction.objectStore('users');
var request = store.get('007');
request.onsuccess = function() {
var result = event.target.result;
result.firstName = 'jack';
store.put(result);
};
}
//删除
function deleteData(key) {
var transaction = db.transaction('users','readwrite');
var store = transaction.objectStore('users');
store.delete(key);
}
//添加
function addData() {
var transaction = db.transaction('users','readwrite');
var store = transaction.objectStore('users');
store.add({ username: "007",
firstName: "James",
lastName: "Bond",
password: "foo"});
}
//因为这里要调用onsucess时候保存的db的实例,但是因为异步操作,如果不用超时调用,可能db还没有获取到!
setTimeout(function() {
updataData();
},500);


先测试将键值为”007”的对象的firstName属性改为jack

结果



然后来删除键值为”007”的对象

代码

setTimeout(function() {
deleteData("007");
},500);


结果



删除成功

测试添加功能

setTimeout(function() {
addData();
},500);


结果



好了,现在创建数据库,给数据库存内容,实现了基本的增删改查。

下面介绍游标查询

使用事务可以直接通过已知的键检索单个对象。而在需要检索多个对象的情况下,则需要在事务内部创建游标。游标就是一指向结果集的指针。与传统数据库查询不同,游标并不提前收集结果。游标指针会先指向结果中的第一项,在接到查找下一项的指令时,才会指向下一项。
在对象存储空间上调用openCursor()方法可以创建游标。与IndexedDB中的其他操作一样,openCursor()方法返回的是一个请求对象,因此必须为该对象指定onsuccess和onerror事件处理程序。


代码

//打开游标
function openCursor() {
var store = db.transaction("users").objectStore("users");
var request = store.openCursor();
request.onsuccess = function() {
var cursor = event.target.result;
if (cursor) {
console.log(cursor.key);
cursor.continue();
}
};
}


测试



键范围

使用游标总让人觉得不那么理想,因为通过游标查找数据的方式太有限了。键范围(Keyrange)为使用游标增添了一些灵活性。键范围由IDBKeyRange的实例表示。


有四种定义键范围的方式。

1. 第一种是使用only()方法,传入你想要取得的对象的键 var onlyRange = IDBKeyRange.only("007);
2. 第二种定义键范围的方式是指定结界集的下界 var lowerRange = IDBKeyRange.lowerBound("007");`               如果你想忽略键为"007"的对象,从它的下一个对象开始,那么可以传入第二个参数true;
3.第三种定义键范围的方式是指定结界集的上界 var lowerRange = IDBKeyRange.upperBound("ace");             如果你不想包含键为指定值的对象,同样,可以传入第二个参数true
4.第四种定义键范围的方式,就是同时指定上、下界。使用bound()方法。这个方法可以接受4个参数:表示下界的键、表示上界的键、可选的表示是否跳过下界的布尔值和可选的表示是否跳过上界的布尔值。


索引(后续补充)

补充说明:我是在高程书上学的indexedDB,其中有一处问题,新版本的IndexedDB规范不支持调用setVersion()方法为数据库指定一个版本号,代替的方法是在open()的时候结合传入表示版本号的字符串,同时使用onupgradeneeded事件代替setVersion()方法。

onupgradeneeded事件会在onsuccess之前被调用


还有就是游标查询的更新和删除出现问题,我还未解决,所以不做示例。(因为是很多都是用自己理解的方式解释,有不严谨的地方,望谅解)

IndexedDB的其他解释博客

谦行大牛博客

张鑫旭大牛博客

范圣刚博客
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: