1、indexedDB 是什么?
IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象(blobs))。该 API 使用索引实现对数据的高性能搜索。虽然 Web Storage 在存储较少量的数据很有用,但对于存储更大量的结构化数据来说力不从心。而 IndexedDB 提供了这种场景的解决方案。
其简单而言,IndexedDB 就是一个基于事务操作的key-value型数前端数据库,其API大多是异步的。
事务:事务是数据库中的一组操作,它们要么全部成功完成,要么全部失败,以确保数据库的一致性和可靠性。事务型数据库主要用于记录和管理各种业务交易和操作,如订单处理、库存管理、银行交易、在线购物等等
一个栗子:
"要么全部成功要么全部失败" 是事务的核心特性之一,称为事务的原子性(Atomicity)。这意味着在事务中的一组操作要么全部成功执行,要么如果有任何一个操作失败,那么整个事务都会被回滚到初始状态,不会产生部分执行的结果。
让我用一个简单的示例来解释这个概念:
假设你正在管理一个银行账户的数据库,其中有两个相关的操作:转账和更新余额。这两个操作必须作为一个事务来执行,以确保数据的一致性。
转账操作:从一个账户A向另一个账户B转账100美元。
更新余额操作:更新账户A和账户B的余额。
现在,如果这两个操作不作为一个事务,可能会发生以下问题:
如果在转账后发生故障,但在更新余额之前,那么资金将丢失,因为A账户已经减少了100美元,但B账户没有收到相应的增加。
如果在更新余额后发生故障,但在转账之前,那么A和B账户都会显示不正确的余额。
为了解决这个问题,你可以将这两个操作放在一个事务中:
开始事务。
执行转账操作:从A账户减去100美元,向B账户增加100美元。
执行更新余额操作:更新A和B账户的余额。
提交事务。
现在,如果在执行任何一个步骤中发生故障,整个事务将被回滚到初始状态,即A和B账户的余额都不会发生变化。这确保了要么全部成功(转账和余额更新都成功),要么全部失败(任何一个步骤失败)的原子性特性。这种方式可以保持银行账户数据的一致性和可靠性。
特点:
- 键值对储存 IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
- 异步 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
- 支持事务 IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
- 同源限制 IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
- 支持二进制储存 IndexedDB 不仅可以储存字符串,还可以储存二进制数据 ArrayBuffer 对象和 Blob 对象。
- 储存空间大 IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。
2、前端本地化存储方式对比
特性cookielocalStoragesessionStorageindexedDB数据生命周期一般由服务器生成,可以设置过期时间;前端采用和js-cookie等组件也可以生成除非被清理,否则一直存在;浏览器关闭还会保存在本地,但是不支持跨浏览器页面关闭就清理刷新依然存在,不支持跨页面交互除非被清理,否则一直存在数据存储大小4K5M5M不限制大小与服务端通信每次都会携带在请求的header 中,对于请求性能有影响;同时由于请求中都带有,所以也容易出现安全问题不参与不参与不参与特点字符串键值对在本地存储数据字符串键值对在本地存储数据字符串键值对在本地存储数据IndexedDB 是一个非关系型数据库(不支持通过 SQL 语句操作)。可以存储大量数据,提供接口来查询,还可以建立索引,这些都是其他存储方案无法提供的能力。
indexedDB支持情况:浏览器支持良好
3、核心概念
数据库:IDBDatabase 对象,数据库有版本概念,同一时刻只能有一个版本,每个域名可以建多个数据库
对象仓库:IDBObjectStore 对象,类似于关系型数据库的表格
索引: IDBIndex 对象,可以在对象仓库中,为不同的属性建立索引,主键建立默认索引
事务: IDBTransaction 对象,增删改查都需要通过事务来完成,事务对象提供了error、abord、complete三个回调方法,监听操作结果
4、怎么用
1.创建或打开数据库
mounted(){const self =this;/*第一个参数:数据库名称,第二个参数:版本号*/this.indexedDB = window.indexedDB.open('test',1);/*监听打开状态*/this.indexedDB.onsuccess=function(e){
console.log('数据库打开成功', e);
self.db = e.target.result;};this.indexedDB.onerror=function(e){
console.log('数据库打开报错');};/*第一次就会触发*/this.indexedDB.onupgradeneeded=function(e){
console.log('数据库升级成功');
self.db = e.target.result;/*判断是否存在user这个store*/if(!self.db.objectStoreNames.contains('user')){const objectStore = self.db.createObjectStore('user',{keyPath:'email'});// 在这里创建索引
objectStore.createIndex('indexId','id',{unique:true});}};},
2.添加操作 :这些操作都是默认依赖于主键的
add(){//transaction 方法用于创建一个事务, 第一个参数是一个数组,包含了你想要在事务中操作的对象存储的名称,第二个参数是字符串,表示事务的类型const transaction =this.db.transaction(['user'],'readwrite');//一旦事务创建成功,我们可以使用 .objectStore() 方法从事务中获取一个指定的对象存储const store = transaction.objectStore('user');const request = store.add({id:2,name:'张三',age:24,email:'[email protected]'});
request.onsuccess=function(e){
console.log('数据写入成功');};
request.onerror=function(e){
console.log('数据写入失败:', e);};},
3.修改操作
update(){const transaction =this.db.transaction(['user'],'readwrite');const store = transaction.objectStore('user');const request = store.put({id:3,name:'李四1',age:24,email:'[email protected]'});
request.onsuccess=function(e){
console.log('数据更新成功');};
request.onerror=function(e){
console.log('数据更新失败:', e);};},
4.获取操作
get(){const transaction =this.db.transaction(['user'],'readwrite');const store = transaction.objectStore('user');const request = store.get('[email protected]');
request.onsuccess=function(e){
console.log('数据获取成功', e.target.result);};
request.onerror=function(e){
console.log('数据获取失败:', e);};},
5.删除操作
handleDelete(){const transaction =this.db.transaction(['user'],'readwrite');const store = transaction.objectStore('user');const request = store.delete('[email protected]');
request.onsuccess=function(e){
console.log('数据删除成功');};
request.onerror=function(e){
console.log('数据删除失败:', e);};},
6.索引
indexGet(){const transaction =this.db.transaction(['user'],'readwrite');const store = transaction.objectStore('user');const index = store.index('indexId');const request = index.get(3);
request.onsuccess=function(e){
console.log('数据获取成功', e.target.result);};
request.onerror=function(e){
console.log('数据获取失败:', e);};},
索引的意义:索引在IndexedDB中具有重要作用,它们用于提高数据检索和查询的性能
索引的实现原理:(b+树)
https://pic4.zhimg.com/80/v2-87fd4faf38729f791003085eaa7464bb_1440w.webp
5.有什么用
离线日志
在线编辑工具(ps,可视化平台)返回上一步
接口数据缓存
等等
6.比较成熟的三方库
localforage
版权归原作者 fengchenguo 所有, 如有侵权,请联系我们删除。