浏览器数据库 IndexedDB 入门

1,928 阅读5分钟

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 sqlIndexedDB两种。相较于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事件,其中函数参数eventtarget属性就是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/…

www.ruanyifeng.com/blog/2018/0…

juejin.cn/post/684490…