indexedDB 前端存储方案

一、前言

广东靓仔在2018年了解过indexedDB,不过没有在日常的开发使用。最近又看到一些关于indexedDB的文章,这里跟小伙伴们一起分享下。

二、特性对比


我们一起来看看cookie、localStorage、sessionStorage、indexDB的特性对比。



231220bk-1.png


caniuse上查看 indexedDB 支持情况,目前浏览器支持情况良好。

231220bk-2.png


三、IndexedDB简介

是什么

IndexedDB 是一种使用浏览器存储大量数据的方法.它创造的数据可以被查询,并且可以离线使用. IndexedDB对于那些需要存储大量数据,或者是需要离线使用的程序是非常有效的解决方法. --- MDN

简单而言,indexedDB就是一个基于事务操作的key-value型数前端数据库.其API大多是异步的

特点

键值对储存 IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。

异步 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。

支持事务 IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。

同源限制 IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。

支持二进制储存 IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象。

储存空间大 IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。储 存 在 电 脑 上 中 的 位 置 为 C:\Users\当 前 的 登 录 用 户\AppData\Local\Google\Chrome\User Data\Default\IndexedDB

核心概念

数据库:IDBDatabase 对象,数据库有版本概念,同一时刻只能有一个版本,每个域名可以建多个数据库

对象仓库:IDBObjectStore 对象,类似于关系型数据库的表格

索引:IDBIndex 对象,可以在对象仓库中,为不同的属性建立索引,主键建立默认索引

事务:IDBTransaction 对象,增删改查都需要通过事务来完成,事务对象提供了error,abord,complete三个回调方法,监听操作结果

操作请求:IDBRequest 对象

指针:IDBCursor 对象

主键集合:IDBKeyRange 对象,主键是默认建立索引的属性,可以取当前层级的某个属性,也可以指定下一层对象的属性,还可以是一个递增的整数

四、indexedDB的使用

创建数据库 & 新建表和索引

var request = window.indexedDB.open('myDatabase', 1);


request.onerror = function(error) {

  console.log('IndexedDB 打开失败', error);

};


request.onsuccess = function(res) {

  console.log('IndexedDB 打开成功', res);

  db = res.target.result;

};


request.onupgradeneeded = function(res) {

  console.log('IndexedDB 升级成功', res);

  db = res.target.result;

  db_table = db.createObjectStore('myDatabase', { keyPath: 'id' });

  db_table.createIndex('indexName', 'name', { unique: false });

};

操作数据api

add() : 增加数据。接收一个参数,为需要保存到对象仓库中的对象。

put() : 增加或修改数据。接收一个参数,为需要保存到对象仓库中的对象。

get() : 获取数据。接收一个参数,为需要获取数据的主键值。

delete() : 删除数据。接收一个参数,为需要获取数据的主键值。

Tips:  add 和 put 的作用类似,区别在于 put 保存数据时,如果该数据的主键在数据库中已经有相同主键的时候,则会修改数据库中对应主键的对象,而使用 add 保存数据,如果该主键已经存在,则保存失败。


添加数据


var store = db.transaction(['myDatabase'], 'readwrite').objectStore('myDatabase');


//方法添加数据

var request = store.add({

  id: 1,

  name: '广东靓仔',

  tip: 'qianduanzaocha',

});


//添加成功

request.onsuccess = function(event) {

  console.log('数据添加成功', event);

};


//添加失败

request.onerror = function(event) {

  console.log('数据添加失败', event);

};

获取数据


var store = db.transaction(['myDatabase']).objectStore('myDatabase');


// get方法获取数据,params 数据的主键

 

var request = store.get(1);


// 获取成功

request.onsuccess = function(event) {

  if (event.target.result) {

    console.log('数据获取成功', event.target.result);

  } else {

    console.log('未获取到数据');

  }

};


// 获取失败

request.onerror = function(event) {

  console.log('数据获取失败', event);

};


删除数据


var store = db.transaction(['myDatabase'], 'readwrite').objectStore('myDatabase');


// delete方法删除数据,params 数据的主键

var request = store.delete(1); 


// 删除成功

request.onsuccess = function (event) {

    console.log('数据删除成功',event);

};


// 删除失败

request.onerror = function (event) {

    console.log('数据删除失败',event);

};

更新数据


var store = db.transaction(['myDatabase'], 'readwrite').objectStore('myDatabase');


// put方法根据主键更新数据,params 数据的主键

var request = store.put({

  id: 2,

  name: '靓仔',

  tip: 'guangdong',

});


// 更新成功

request.onsuccess = function(event) {

  console.log('数据更新成功', event);

};


// 更新失败

request.onerror = function(event) {

  console.log('数据更新失败', event);

};

使用游标


var store = db.transaction(['myDatabase']).objectStore('myDatabase');


// index方法获取索引对象,get方法获取数据,params 数据的索引

var request = store.index('indexName').get('靓仔'); 


// 获取成功

request.onsuccess = function (event) {

     console.log('通过索引获取数据成功',event.target.result);

};


// 获取失败

request.onerror = function (event) {

    console.log('通过索引获取数据失败',event);

};

getAll()是用来获取整张表的数据


IDBKeyRange对象


索引的有用之处,还在于可以指定读取数据的范围。这需要用到浏览器原生的IDBKeyRange对象。(指定条件获取数据)


IDBKeyRange对象的作用是生成一个表示范围的Range对象。生成方法有四种:


lowerBound方法:指定范围的下限。


upperBound方法:指定范围的上限。


bound方法:指定范围的上下限。


only方法:指定范围中只有一个值。


// All keys ≤ x 

var r1 = IDBKeyRange.upperBound(x);


// All keys < x 

var r2 = IDBKeyRange.upperBound(x, true);


// All keys ≥ y 

var r3 = IDBKeyRange.lowerBound(y);


// All keys > y 

var r4 = IDBKeyRange.lowerBound(y, true);


// All keys ≥ x && ≤ y 

var r5 = IDBKeyRange.bound(x, y);


// All keys > x &&< y 

var r6 = IDBKeyRange.bound(x, y, true, true);


// All keys > x && ≤ y 

var r7 = IDBKeyRange.bound(x, y, true, false);


// All keys ≥ x &&< y 

var r8 = IDBKeyRange.bound(x, y, false, true);


// The key = z 

var r9 = IDBKeyRange.only(z);

参考链接:


https://www.w3cschool.cn/javascript_guide/javascript_guide-rcfy26a4.html#toc9


https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/transaction


https://caniuse.com/?search=indexedDB




作者:广东靓仔


欢迎关注:前端早茶