(小编最近在研究indexedDB数据库,在网上看的文档都有些不好理解,像小编这个接触过mySql,Oracle,SQL Server的人看了都是云里雾里的,所以决定自己写一篇关于indexedDB是数据库的博文出来帮助小白更直白的了解,转载请注明出处,谢谢)
为什么要使用indexedDB浏览器数据库?
随着浏览器的功能不断增强,越来越多的网站开始考虑,将大量数据储存在客户端,这样可以减少从服务器获取数据,直接从本地获取数据。现有的浏览器数据储存方案,都不适合储存大量数据:Cookie 的大小不超过4KB,且每次请求都会发送回服务器;LocalStorage 在 2.5MB 到 10MB 之间(各家浏览器不同),而且不提供搜索功能,不能建立自定义的索引。
通俗地说**,IndexedDB 就是浏览器提供的本地数据库**,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。这些都是 LocalStorage 所不具备的。就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。
IndexedDB 具有以下特点。
(1)键值对储存。 IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
(2)异步。 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
(3)支持事务。 IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
(4)同源限制 IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
(5)储存空间大 IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。
(6)支持二进制储存。 IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。
接下来我们就来看看这个高大上nb带闪电的玩意怎么玩
如何使用?
首先,创建打开数据库
// indexedDB浏览器数据库是挂载在window上的,在其数据库对象上有一个open方法
/**
* open方法接收两个参数,第一个参数字符数是数据库名,第二个参数为数据库版本号
* open方法可以用来打开数据库也可以用来创建数据库,只传一个数据库名的时候,如果数据库名已存在默认打开当前版本数据库,如果不存在则会新建一个
* 数据库,第二个参数是版本号,不传的时候打开默认是当前版本,创建默认是1
* 返回一个当前数据库的IDBOpenDBRequest对象(小编理解就是当前数据库的一个对象实例),这个实例自带了一些事件
* 常用的有
* error =》数据库打开失败
* onsuccess =》数据库打开成功(就可以通过其result属性拿到数据库对象了)
* upgradeneeded =》数据库升级事件,如果指定的版本号大于当前数据库版本号就会发生数据库升级事件,这个时候则需要使用事件对象的event.taget.result拿到数据库实例
*
* 如果是新建数据库,由于数据库的从无到有属于版本升级,所以会先触发request的onupgradeneeded事件然后再触发其onsuccess事件
*
*/
var request=window.indexedDB.open("dataNames");
//如果要删除数据库:indexDB.deleteDatabase('数据库名');
这样我们就在window上创建了一个浏览器数据库了,库名叫做“dataNames”,既然创建了数据库,那么就要建表了,这个window.indexedDB.open(“dataNames”);方法创建数据库的时候会返回一个对象,这个对象上有三个事件
数据库打开成功和失败事件大家都好理解,那么这个数据库版本升级事件是个什么鬼?这个事件就是我们创建数据表的地方了,数据库版本升级是啥意思呢?我们使用 var request=window.indexedDB.open(“dataNames”);方法时如果第二个参数也就是版本号参数大于当前数据版本号就会发生数据库版本升级事件,否则就只会触发数据库打开成功或者失败事件而不会触发版本升级事件
那么,直接上创建表的代码
// 数据库版本升级事件
request.onupgradeneeded=function (ev) {
//拿到数据库实例对象,其中包含了对数据库表的的创建编辑等功能
db=ev.target.result;
var objectStore;
//判断我们要创建的person表是否已经存在,数据库实例的objectStoreNames中放的是我们的所有表的集合
//contain方法查看数据库表集合中是否存在某种表
if (!db.objectStoreNames.contains('person1')) {
//使用数据库实例的createObjectStore方法创建对象仓库(其实就是数据表),第一个参数字符串就是数据表名,第二个表示
//设置这个表中的id为主键(主键是唯一的,方便迅速索引查找)
objectStore = db.createObjectStore('person1', { keyPath: 'id' });
//使用createIndex为这个数据表添加索引(其实就是列名),三个参数分别是:列名,列名所在属性,配置对象(是否包含重复的值)
objectStore.createIndex('name', 'name', { unique: false });
objectStore.createIndex('email', 'email', { unique: true });
}
};
这就创建出来一张名为person1的表了,设置了这个表的id列为主键列,为其增加了一个name列和一个email列
那么有了表了接下来就为给表添加数据了,window.indexedDB.open(“dataNames”);方法创建数据库的时候会先触发onupgradeneeded事件然后触发onsuccess数据库打开成功事件
// 数据库打开(已有就打开,没有就创建后打开)成功事件
request.onsuccess=function (ev) {
//拿到数据库实例对象,其中包含了对数据库表的的创建编辑等功能
db=ev.target.result;
console.log(db);
//调用add方法向我们创建的数据库表中添加数
add();
};
// add方法用来项数据库中存入数据
function add() {
//indexedDB数据库的读写都是通过事务来完成的,
// 通过数据库对象实例.transaction(['表名'],‘只读或读写’)来创建一个指定表的事务
// 只读:read,不能修改数据库数据,可以并发执行
// 读写:readwrite,可以进行读写操作
// 版本变更:verionchange
console.log(db);
var request = db.transaction(['person1'], 'readwrite');
//通过创建的表事务的pbjectStore(‘表名’)拿到我们要的数据库指定表对象
request=request.objectStore('person1');
//通过表对象的add方法向数据库中写入数据返回一个IDBRequest对象,对手上的onsuccess事件是数据写入成功事件,onerror是数据写入失败事件
console.log(request);
request =request.add({ id: 1, name: '王阔', age: 24, email: '[email protected]' });
//数据写入成功
request.onsuccess = function (event) {
console.log('数据写入成功');
};
console.log(request);
//数据写入失败
request.onerror = function (event) {
console.log('数据写入失败');
}
}
这样我们就向数据库的person1表中添加了一条数据了,也可以添加多条,
那么添加完数据就要在其他同域的页面上获取数据了,首先还是打开数据库
//数据库打开(已有就打开,没有就创建后打开)成功事件
request.onsuccess=function (ev) {
//拿到数据库实例对象,其中包含了对数据库表的的创建编辑等功能
db=ev.target.result;
console.log('数据库打开成功');
//调用read方法向我们创建的数据库表中拿取数据
read();
};
read方法就是我们获取数据的方法
//从indexedDB数据库中读取数据
function read() {
//创建一个指定表的事务对象
var transaction = db.transaction(['person1']);
//获取指定表的实例
var objectStore = transaction.objectStore('person1');
//通过get(索引)拿取数据
var request=objectStore.get(1);
//获取全部数据 var request = objectStore.getAll();
//获取数据总数 var request = objectStore.count();
// 数据拿取失败
request.onerror = function(event) {
reject();
console.log('事务失败');
};
//数据拿取成功
request.onsuccess = function(event) {
//这里数据拿取成功的话,传入的事件对象中的target的result就是我们拿取到的数据了
//如果上面是用objectStore.get(1);拿取的那就是单个数据
//使用objectStore.getAll();拿取的就是全部数据
//不管拿取的那种数据都会被存到事件对象的target.result中去
if (request.result) {
console.log('Name: ' + request.result.name);
console.log('Age: ' + request.result.age);
console.log('Email: ' + request.result.email);
} else {
console.log('未获得数据记录');
}
};
}
这里需要注意的是开启数据库是异步操作,而拿取数据也是异步操作,也就是说我们如果在表对象的onsuccess方法之外获取数据是获取不到的
总结一下小编研究之中犯过的错误:
1.数据库版本号更新的时候创建之前版本已经存在的表,这个不会报错,但是如果监测会发现进入onerror事件中去了
2.导致数据写入失败的原因:我们添加列的时候第三个参数如果是true那就是不允许重复,添加的数据不允许重复列如果重复了会导致数据写入失败,写入得数据主键列有重复也回导致数据写入失败,还有一些其他的数据格式原因等
这些就是小编整理的学习indexedDB浏览器数据库的笔记,后续还会出一些深层一点的笔记,随后附上indexedDB对象图和完整代码
小编用来两个文件,一个添加数据一个获取数据
添加数据
// indexedDB浏览器数据库是挂载在window上的,在其数据库对象上有一个open方法
/**
* open方法接收两个参数,第一个参数字符数是数据库名,第二个参数为数据库版本号
* open方法可以用来打开数据库也可以用来创建数据库,只传一个数据库名的时候,如果数据库名已存在默认打开当前版本数据库,如果不存在则会新建一个
* 数据库,第二个参数是版本号,不传的时候打开默认是当前版本,创建默认是1
* 返回一个当前数据库的IDBOpenDBRequest对象(小编理解就是当前数据库的一个对象实例),这个实例自带了一些事件
* 常用的有
* error =》数据库打开失败
* onsuccess =》数据库打开成功(就可以通过其result属性拿到数据库对象了)
* upgradeneeded =》数据库升级事件,如果指定的版本号大于当前数据库版本号就会发生数据库升级事件,这个时候则需要使用事件对象的event.taget.result拿到数据库实例
*
* 如果是新建数据库,由于数据库的从无到有属于版本升级,所以会先触发request的onupgradeneeded事件然后再触发其onsuccess事件
*
* indexDB主要对象介绍:
* IDBFactory:打开数据库的工厂对象,用于打开数据库,并管理数据库版本。
* IDBOpenDBRequest:请求对象,对数据库的访问、操作都是基于请求的,通过请求对象获取其他DOM对象。
* IDBDatabase:数据库对象,封装了对数据库表的创建、编辑等功能。
* IDBObjectStore:类似于数据库的数据表。
* IDBIndex:数据库索引对象,用于创建数据表的索引。
* IDBTransaction:数据库事物控制对象。
* IDBCursor:数据库访问游标,用于访问数据。
*/
var request=window.indexedDB.open("dataNames",3);
//如果要删除数据库:indexDB.deleteDatabase('数据库名');
var db;
// 数据库打开(已有就打开,没有就创建后打开)成功事件
request.onsuccess=function (ev) {
//拿到数据库实例对象,其中包含了对数据库表的的创建编辑等功能
db=ev.target.result;
//调用add方法向我们创建的数据库表中添加数
add();
};
// 数据库版本升级事件
request.onupgradeneeded=function (ev) {
//拿到数据库实例对象,其中包含了对数据库表的的创建编辑等功能
db=ev.target.result;
var objectStore;
//判断我们要创建的person表是否已经存在,数据库实例的objectStoreNames中放的是我们的所有表的集合
//contain方法查看数据库表集合中是否存在某种表
if (!db.objectStoreNames.contains('person1')) {
//使用数据库实例的createObjectStore方法创建对象仓库(其实就是数据表),第一个参数字符串就是数据表名,第二个表示
//设置这个表中的id为主键(主键是唯一的,方便迅速索引查找)
objectStore = db.createObjectStore('person1', { keyPath: 'id' });
console.log(objectStore);
//使用createIndex为这个数据表添加索引(其实就是列名),三个参数分别是:列名,列名所在属性,配置对象(是否包含重复的值)
objectStore.createIndex('name', 'name', { unique: false });
objectStore.createIndex('email', 'email', { unique: true });
}
};
// 数据库打开失败事件
request.onerror=function (e) {
console.log("数据库启动失败")
}
// add方法用来项数据库中存入数据
function add() {
//indexedDB数据库的读写都是通过事务来完成的,
// 通过数据库对象实例.transaction(['表名'],‘只读或读写’)来创建一个指定表的事务
// 只读:read,不能修改数据库数据,可以并发执行
// 读写:readwrite,可以进行读写操作
// 版本变更:verionchange
var request = db.transaction(['person1'], 'readwrite');
//通过创建的表事务的pbjectStore(‘表名’)拿到我们要的数据库指定表对象
request=request.objectStore('person1');
//通过表对象的add方法向数据库中写入数据返回一个IDBRequest对象,对手上的onsuccess事件是数据写入成功事件,onerror是数据写入失败事件
console.log(request);
request =request.add({ id: 4, name: '王阔', age: 24, email: '[email protected]' });
//数据写入成功
request.onsuccess = function (event) {
console.log('数据写入成功');
};
console.log(request);
//数据写入失败
request.onerror = function (event) {
console.log('数据写入失败');
}
}
//删除指定id的数据
function deleteInif() {
var request = db.transaction(['person1'], 'readwrite');
request=request.objectStore('person1');
request.delete(5);
}
//清空表记录
function clearInif() {
var request = db.transaction(['person1'], 'readwrite');
request=request.objectStore('person1');
request.clear();
}
var request=window.indexedDB.open("dataNames");
var db;
//数据库打开(已有就打开,没有就创建后打开)成功事件
request.onsuccess=function (ev) {
//拿到数据库实例对象,其中包含了对数据库表的的创建编辑等功能
db=ev.target.result;
console.log('数据库打开成功');
//调用read方法向我们创建的数据库表中拿取数据
read();
};
//从indexedDB数据库中读取数据
function read() {
//创建一个指定表的事务对象
var transaction = db.transaction(['person1']);
//获取指定表的实例
var objectStore = transaction.objectStore('person1');
//通过get(索引)拿取数据
var request=objectStore.get(1);
//获取全部数据 var request = objectStore.getAll();
//获取数据总数 var request = objectStore.count();
// 数据拿取失败
request.onerror = function(event) {
console.log('事务失败');
};
//数据拿取成功
request.onsuccess = function(event) {
//这里数据拿取成功的话,传入的事件对象中的target的result就是我们拿取到的数据了
//如果上面是用objectStore.get(1);拿取的那就是单个数据
//使用objectStore.getAll();拿取的就是全部数据
//不管拿取的那种数据都会被存到事件对象的target.result中去
console.log(event.target.result);
if (request.result) {
console.log('Name: ' + request.result.name);
console.log('Age: ' + request.result.age);
console.log('Email: ' + request.result.email);
} else {
console.log('未获得数据记录');
}
};
}