IndexedDB 是一个事务型数据库系统,类似于基于 SQL 的 RDBMS。然而,不像 RDBMS 使用固定列表,IndexedDB 是一个基于 JavaScript 的面向对象数据库。IndexedDB 允许你存储和检索用 键索引的对象;可以存储 结构化克隆算法支持的任何对象。dexie.js是一个对浏览器indexexDB的包装库,使得我们可以更方便地操作indexedDB。
IndexedDB存储
IndexedDB是一种在浏览器中存储数据的机制,提供了一个类似于关系型数据库的方式来存储和检索数据,但是它是在客户端执行的,而不是在服务器端执行的。这使得IndexedDB成为一种非常适合在Web应用程序中存储大量数据的方式。
IndexedDB的主要优点之一是它可以存储大量数据,因为它是在客户端执行的,而不是在服务器端执行的。这意味着数据的存储和检索速度非常快,因为它不需要通过网络连接来访问数据。此外,IndexedDB还支持事务,这意味着可以在一个事务中执行多个操作,然后将这些操作一起提交或回滚。
IndexedDB还支持索引,可以根据特定的属性对数据进行快速检索。这使得IndexedDB非常适合在应用程序中执行复杂的查询操作。此外,IndexedDB还支持存储二进制数据,可以存储图像、视频和其他类型的文件。
IndexedDB是一个基于事件的API,可以使用事件来处理数据的存储和检索操作。这种方式使得IndexedDB非常灵活,可以根据需要来处理数据的存储和检索操作。
IndexedDB操作时不会锁死浏览器,用户依然可以进行其他操作,它所有的API都是异步操作,异步设计时为零防止大量数据的读写拖慢网页的表现。而且每一个数据库对应创建它的域名,网页只能访问自身域名下的数据库,而不能访问跨域名的数据库
IndexedDB使用对象存储空间来存储数据,每个对象存储空间都包含多个对象。每个对象都有一个主键,您可以使用主键来检索数据。此外,还可以在对象存储空间中创建索引,以便更快地检索数据。
此外,IndexedDB还支持版本控制,可以对数据库进行升级或降级。这使得IndexedDB非常适合在应用程序中进行数据迁移操作。
IndexedDB是一种非常强大和灵活的数据存储机制,它可以在Web应用程序中存储大量数据,并且能够快速地检索这些数据。如果需要在Web应用程序中存储大量数据,并且需要执行复杂的查询操作,那么IndexedDB是一个非常好的选择。
IndexedDB常用概念
- 数据库(Database):IndexedDB中的数据库是一个包含对象存储空间(Object Store)和索引(Index)的存储单元。一个数据库可以包含多个对象存储空间,每个对象存储空间可以存储多个对象。
- 对象存储空间(Object Store):对象存储空间是IndexedDB中用来存储数据对象的地方,类似于关系型数据库中的表。每个对象存储空间都有一个名称和一个键路径(Key Path)用来标识主键。
- 索引(Index):索引是用来加快数据检索速度的工具,可以根据特定的属性来创建索引,以便更快地检索数据。
- 事务(Transaction):事务是一组数据库操作的集合,可以确保这些操作要么全部执行成功,要么全部失败。通过事务,可以确保数据的一致性和完整性。
- 主键(Primary Key):每个对象在对象存储空间中都有一个主键,用来唯一标识这个对象。主键可以是一个属性值,也可以是自动生成的键值。
- 版本(Version):IndexedDB中的数据库版本用来管理数据库结构的变化,可以通过版本控制来升级或降级数据库。
- 事件(Event):IndexedDB是基于事件的API,通过监听不同的事件(如打开数据库、创建对象存储空间、添加数据等),可以实现相应的数据操作和处理。
- 二进制数据(Binary Data):IndexedDB支持存储二进制数据,这意味着可以存储图像、视频和其他类型的文件。
Dexie.js
尽管IndexedDB是一个功能强大的客户端存储解决方案,但它也存在一些缺点,特别是在使用原生IndexedDB API时。一些原生IndexedDB的缺点包括:
- 复杂性:原生IndexedDB API相对复杂,对开发人员来说学习曲线较陡。需要编写大量的代码来执行简单的数据库操作,如打开数据库、创建对象存储空间、执行查询等。这增加了开发的复杂性和难度。
- 低级别API:原生IndexedDB API是一个低级别的API,需要处理很多细节和底层操作,如事务管理、版本控制、索引创建等。这使得开发人员需要花费更多的时间和精力来处理这些细节,增加了开发成本和工作量。
- 兼容性:原生IndexedDB API的兼容性在不同的浏览器之间存在一些差异,特别是在旧版的浏览器上。这可能导致在不同浏览器上编写不同的代码来处理兼容性问题,增加了开发和维护的难度。
- 缺乏查询语言:原生IndexedDB API没有内置的查询语言,开发人员需要手动编写复杂的查询操作,如范围查询、过滤查询和排序查询等。这增加了开发的复杂性和难度。
- 存储限制:原生IndexedDB在存储数据方面存在一些限制,如存储容量限制、存储性能限制等。这可能会影响应用程序的性能和扩展性。
- 缺乏高级功能:原生IndexedDB API缺乏一些高级功能,如数据同步、数据加密等。这可能导致在一些应用场景下需要额外的开发工作来实现这些高级功能。
通过使用IndexedDB的封装库如Dexie.js等,可以简化IndexedDB的复杂性,提供更加易用和高级的API,帮助开发人员更加高效地使用IndexedDB来存储和检索数据。
Dexie.js是一个基于IndexedDB的封装库,它提供了一个简单而强大的API,使得在浏览器中使用IndexedDB变得更加容易和便捷。Dexie.js的设计目标是简化IndexedDB的复杂性,提供一种更加直观和易于使用的方式来操作IndexedDB数据库。
Dexie.js主要特点包括:
- 简单易用的API:Dexie.js提供了一个简单易用的API,使得创建、打开和操作IndexedDB数据库变得非常容易。您可以通过几行代码就可以创建一个新的数据库,并且定义对象存储空间和索引。
- 强大的查询功能:Dexie.js提供了一套强大的查询API,使得在数据库中执行复杂的查询操作变得非常简单。您可以轻松地执行范围查询、过滤查询和排序查询等操作,而无需编写复杂的IndexedDB查询语句。
- 支持事务操作:Dexie.js支持事务操作,这意味着您可以在一个事务中执行多个操作,并且可以将这些操作一起提交或回滚。这使得在应用程序中执行复杂的数据操作变得更加容易和可靠。
- 版本控制:Dexie.js提供了一种便捷的方式来处理版本控制。您可以轻松地升级或降级数据库的版本,并且可以在数据库升级时执行自定义的操作。这使得在应用程序中进行数据迁移操作变得更加简单和可靠。
- 事件处理机制:Dexie.js提供了一套强大的事件处理机制,使得在数据库操作期间可以方便地处理各种事件。您可以监听数据库的打开、关闭、升级等事件,并且可以根据需要来执行相应的操作。
Dexie.js是一个功能丰富且易于使用的IndexedDB封装库,它可以帮助开发人员更加轻松地在浏览器中使用IndexedDB来存储和检索数据。它提供了许多方便的功能和特性,可以提高开发效率并改善应用程序的性能和稳定性。
操作流程
获取一个数据库实例
const iDbData = new Dexie('iDbData');
通过调用**new Dexie()**可以创建一个新的IndexedDB数据库实例。如果已经存在,就会返回已经存在的数据库的一个实例,如果不存在,就会新建一个数据库,并返回该数据库的一个实例。'iDbData’表示为数据库名。
定义对象存储空间和索引等数据库结构_
// 定义对象存储空间和索引等数据库结构
iDbData.version(lastVersion).stores({
myTable: '++id,StorageTime', // Primary key and indexed props,默认第一个为主键
});
lastVersion:表示定义数据库的版本号。在IndexedDB中,数据库的版本号用来管理数据库结构的变化,包括新增、删除或修改对象存储空间、索引等操作。如果需要对数据库结构进行更改,可以通过增加版本号来定义新的数据库版本,并在新的版本中进行相应的操作。由于dexiejs需要兼容IE的一个BUG,所以在实际建库的时候版本号都会乘以10,如果这里lastVersion传0.1,实际建的库的版本就是 1,如果这里lastVersion传1,实际建的库的版本就是 10。<br />myTable是一个对象存储空间,相当于mysql中的表,后面跟着的是索引,默认第一字段为主键,在对象存储空间中只需要定义索引字段即可,无需定义表的所有字段,如果某个字段存储的是图片数据(imageData),视频(arrayBuffer),或者特别大的字符串,不建议加入索引列表。<br />常用的四种索引
- 主键(自增):索引列表的第一个总会被当做主键,如上例中的,如果主键前有++ 符号,说明这个字段是自增的。如++id表示主键索引且自增,默认为数值类型,但是对于插入的id为字符串类型数据并不敏感。
- 唯一索引:如果某个索引的字段的值在所有记录中是唯一的,那么可以在它前面加& 号
import Dexie from 'dexie';
export default function uniqueIdxTable() {
}
const uniqueIdxDB = new Dexie('uniqueIdxDB');
uniqueIdxDB.version(1).stores({
myUniqueIdxTable: '++id,&uniqueIndex', //&表示唯一索引
});
const data1 = {
id: 1,
uniqueIndex: '1'
}
const data2 = {
id: 2,
uniqueIndex: '1'
}
// 可以插入
uniqueIdxDB.myUniqueIdxTable.put(data1)
// 插入失败
// 警告:Unhandled rejection: ConstraintError: Unable to add key to index 'uniqueIndex': at least one key does not satisfy the uniqueness requirements.
// ConstraintError: Unable to add key to index 'uniqueIndex': at least one key does not satisfy the uniqueness requirements.
uniqueIdxDB.myUniqueIdxTable.put(data2)
- 多值索引:多值索引是在表中的某个字段上创建的索引,但该字段的值是一个数组或集合,用于支持对该字段的多个值进行检索
import Dexie from 'dexie';
export default function multiEntryIdxTable() {
}
const multiEntryIdxDB = new Dexie('multiEntryIdxDB');
multiEntryIdxDB.version(1).stores({
myMultiEntryIdxTable: '++id,name,*tags', // *表示多值索引
});
const data1={
id:1,
name:'张三',
tags:['活泼','开朗']
}
const data2={
id:2,
name:'李四',
tags:['活泼','乐观']
}
multiEntryIdxDB.myMultiEntryIdxTable.add(data1)
multiEntryIdxDB.myMultiEntryIdxTable.add(data2)
multiEntryIdxDB.myMultiEntryIdxTable.where('tags').anyOf('活泼').toArray().then(res=>
console.log("myMultiEntryIdxTable SELECT:"+JSON.stringify(res))
)
索引存储结构如下:
- 复合索引:复合索引是在多个字段上创建的索引,用于支持对多个字段的组合值进行检索。复合索引相当于mysql中的联合索引,且符合最左匹配原则
import Dexie from 'dexie';
export default function compoundIdxTable() {
}
const compoundIdxDB = new Dexie('compoundIdxDB');
compoundIdxDB.version(1).stores({
myCompoundIdxTable: '++id,[firstName+lastName]', // []括起来的复合索引
});
const data1 = { id: 1, firstName: 'zhang', lastName: 'san', }
const data2 = { id: 2, firstName: 'zhang', lastName: 'si', }
const data3 = { id: 3, firstName: 'wang', lastName: 'wu', }
compoundIdxDB.myCompoundIdxTable.add(data1);
compoundIdxDB.myCompoundIdxTable.add(data2);
compoundIdxDB.myCompoundIdxTable.add(data3);
两个字段作为一个密钥,索引存储结构如下:
基本增删查改
- 新增
add()方法用于将数据插入到数据库表中,如果数据库表中已存在具有相同主键的记录,则插入操作将失败,不会覆盖已有记录。
iDbData.myTable.add(data)
- 修改
put()方法用于将数据插入或更新到数据库表中。如果数据库表中已存在具有相同主键的记录,则该记录将被更新为新的值。如果数据库表中不存在具有相同主键的记录,则将插入新记录。鉴于add()方法执行时如果已经存在主键一样的数据,就会报错,推荐总是使用put()操作来新增和更新记录,而尽量不用add()操作。
iDbData.myTable.put(data)
- 删除
delete()方法用于从数据库表中通过主键删除符合指定条件的记录
iDbData.myTable.delete(id)
- 查询
get()方法用于从数据库表中通过主键获取符合指定条件的单个记录。
iDbData.myTable.get(id)
可以建立一个索引记录插入时的时间戳,进行超时删除缓存操作:
// 删除超过1天的数据
this.delDataByTimeout(24 * 60 * 60 * 1000)
delDataByTimeout(timeStampDiff){
// 获取当前时间的时间戳
let currentTime = new Date().getTime();
// 计算超过的时间戳阈值
let thresholdTimestamp = currentTime - timeStampDiff;
// 删除时间超过一天的数据
return iDbData.myTable.where('StorageTime').below(thresholdTimestamp).delete();
}
完整代码:https://download.csdn.net/download/weixin_45061924/88944335