IndexedDB
1.概念
1)浏览器提供的本地数据库,可以使用网页脚本创建和操作;
2)允许储存大量数据,提供查找接口,还能建立索引
2.特点
1)键值对储存。 IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
2)异步。 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
3)支持事务。 IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
4)同源限制 IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
5)储存空间大 IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。
6)支持二进制储存。 IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。
3.各存储方案比较
应用场景
当我们进行一些较大的SPA页面开发时,我们会需要进行一些数据的本地存储。
当数据量不大时,我们可以通过SessionStorage或者LocalStorage来进行存储,但是当数据量较大,或符合一定的规范时,我们可以使用数据库来进行数据的存储。
在浏览器提供的数据库中,共有web sql和IndexedDB两种。相较于HTML5已经废弃的web sql来说,更推荐大家使用IndexedDB。
结构
类比sql型数据库,IndexedDB中的DB(数据库)就是sql中的DB,而Object Store(存储空间)则是数据表,Item则等于表中的一条记录。
基本操作
1.创建库及表
//创建一个名称为gomall且版本为2的数据库,返回一个请求
var request = indexedDB.open("gomall", this.version);
//增加数据库版本号时,会触发onupgradeneeded事件(会在onsuccess之前被调用)
request.onupgradeneeded = function (e) {
//创建对象存储空间(ObjectStore),类似表,goods是表名,date是主键,存储的是JSON
e.target.result.createObjectStore("goods", {
keyPath: "date",
autoIncrement: true,
});
console.log("初始化数据库成功!");
};
//绑定回调事件,成功时
request.onsuccess = function (e) {
db = e.target.result;
console.log("创建数据库成功");
};
//失败时
request.onerror = function (e) {
console.log("错误:" + e.target.errorCode || e.target.error);
};
调用indexedDB.open接口时,如果当前数据库不存在,则会创建一个新的数据库。
当数据库建立连接时,会返回一个IDBOpenDBRequest对象。
在连接建立成功时,会触发onsuccess事件,其中函数参数event的target属性就是request对象。
而在数据库创建或者版本更新时,会触发onupgradeneeded事件。
注:只能在onupgradeneeded回调函数中创建存储空间,而不能在数据库打开后的success回调函数中创建。
2.添加数据
// 打开数据库
let request = indexedDB.open("gomall", 2);
request.onsuccess = function (e) {
//从数据库中获得存储对象,表
let goods = e.target.result.transaction("goods", "readwrite").objectStore("goods");
goods.add({
date: new Date().getTime(),
name: '苹果',
price: 15,
});
console.log("添加数据成功!");
};
注:更新某一条数据objectStore.put(),put方法不仅能够修改现有数据,也能够往存储空间中增加新的数据。
3.查询数据
let request = indexedDB.open("gomall", 2);
request.onsuccess = function (e) {
let objectStore = e.target.result.transaction("goods").objectStore("goods");
objectStore.openCursor().onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
this.tableData.push(cursor.value);
cursor.continue();
} else {
console.log("没有更多数据了!");
}
};
};
1)使用getAll()获取所有数据。
2)使用get(key)获取单条数据,这里的key是要获取数据的主键的值。
3)使用openCursor(),这是indexedDB的指针对象,他也是异步的所以监听success方法,然后使用cursor.contiune()移动指针。
通过游标(cursor)来查看数据的值存在性能损失,因为对象是懒创建的。而如果使用像getAll这样的方法,浏览器不得不同时创建所有的对象。如果只是想用游标来看数据的键,那么使用游标是更有效的选择。
4.删除数据
let request = indexedDB.open("gomall", 2);
request.onsuccess = function (e) {
//从数据库中获得存储对象,表
let goods = e.target.result.transaction("goods", "readwrite").objectStore("goods");
//执行删除操作
let request = goods.delete(rows[index].date);
//成功时的回调
request.onsuccess = function (e) {
console.log(e.target.result);
};
};
5.使用索引
// objectStore.createIndex('name', 'name', { unique: false }); 必须在创建存储空间后就执行
let request = objectStore.index("name").getAll(_this.formData.value);
request.onsuccess = function (e) {
console.log(e.target.result);
};
索引的意义在于,可以让你搜索任意字段,也就是说从任意字段拿到数据记录。如果不建立索引,默认只能搜索主键(即从主键取值)。
IDBIndex.getAll(query, count); 说明:query:一个键,也可以是创建的索引;count:希望返回的数据数
总结
IndexedDB是替代关系型数据库web sql的产品,能够对大量数据进行存储。在许多需要运用离线存储的场景下,它能够给我们提供有效的支撑。
但是,IndexedDB在使用过程中仍然需要避免可能会出现的一些问题,或者对可能导致的不利影响有一定的容错处理。
参考文章:
developer.mozilla.org/zh-CN/docs/…