什么是indexDB?
IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象(blobs))。该 API 使用索引实现对数据的高性能搜索。虽然 Web Storage 在存储较少量的数据很有用,但对于存储更大量的结构化数据来说力不从心。而 IndexedDB 提供了这种场景的解决方案。本页面 MDN IndexedDB 的主要引导页 - 这里,我们提供了完整的 API 参考和使用指南,浏览器支持细节,以及关键概念的一些解释的链接。——MDN
为什么要使用indexDB?
其实在前面的MDN对indexDB的介绍中已经说明了,虽然 Web Storage 在存储较少量的数据很有用,但对于存储更大量的结构化数据来说力不从心。而 IndexedDB 提供了这种场景的解决方案
。简而言之,indexDB就是为特殊场景下需要客户端缓存更多的数据,并实现更高性能搜索数据的一种方式。属于是storage的plus++版本
IndexDB的兼容性如何?
作为前端开发,在使用任何一种新属性或API时,主动查看兼容性感觉已经是被动技能了(虽然在2023年的今天,对兼容性的要求已经不再像以前那么强了 )
可以看到,在2023年的今天,indexDB的兼容性已经很不错了。所以这还不快快学起来
IndexDB的使用
- 1、创建并打开一个数据库
- 2、添加数据库数据
- 3、删除数据库数据
- 4、更新数据库数据
- 5、获取数据库数据
创建并打开一个数据库
let db;
const request = window.indexDB.open(name, version);
request.onsuccess = e => {
db = e.target.result;
console.log('数据库打开成功会执行');
};
request.onupgradeneeded = e => {
console.log('数据库创建和更新会执行');
};
request.onerror = error => {
console.log('数据库打开失败会执行');
};
// onupgradeneeded回调会比onsuccess先触发
可以看到打开一个数据库需要2个参数,第一个参数name
是数据库的名称,第二个参数version
是数据库的版本(version只能传入整数,不能传入浮点数,否则它将会被转变成离它最近的整数,这可能导致 upgradeneeded
事件不会被触发)
执行完毕后可以在控制台的Application
中找到该数据库,如下图
添加数据库数据
const data = {
id: Date.now(),
name: '张三',
age: 18,
};
// 因为db是在回调中赋值,使用定时器为了保证db能正常访问,不知道为什么可以去了解事件循环
setTimeout(() => {
// 1、创建事务
const transaction = db.transaction([storeName], 'readwrite');
// 2、访问对象仓库
const store = transaction.objectStore(storeName);
// 3、向仓库添加数据
store.add(data);
store.onsuccess = e => {
console.log('数据添加成功后触发');
};
transaction.oncomplete = e => {
console.log('所有数据添加完毕后触发');
};
transaction.onerror = error => {
console.log('数据添加失败后触发');
};
}, 1500);
在indexDB中想要操作数据库,就必须开启一个事务(transaction)
。事务
来源于数据库对象。
开启一个事务
需要2个参数:
storeNames
:作用域,想要访问的对象仓库数组。可以传控数组但没必要事务模式
:readonly
或者readwrite
该方法返回一个可以访问对象仓库的事务对象,使用该对象就可以操作对象仓库。
添加数据成功后,可以如下图所示刷新数据库
删除数据库数据
在indexDB
中删除数据有2种方式,因为创建对象仓库
时也有2种配置。删除就是根据创建对象仓库
时定义的方式找到相应的数据进行删除
1、创建对象仓库
在
indexDB
中,onupgradeneeded
是我们唯一可以修改数据库结构的地方。在这里面,我们可以创建和删除对象存储空间以及构建和删除索引。
onupgradeneeded
就是创建/更新数据库的回调
。很好理解,使用数据库一共就3个回调:onsuccess
,onerror
和onupgradeneeded
。我们不可能在失败和成功才进行数据库的一些设置,所以只有在onupgradeneeded
时对数据库进行一些配置,如下:
// 自动忽略剩下代码,只关注主要部分
let objectStore;
request.onupgradeneeded = e => {
// 建立对象仓库来存储数据
// 1、根据数据的某个字段作为键路径,要求后续数据必须有该字段
objectStore = db.createObjectStore('yourStoreName', { keyPath: 'id' });
// 2、使用键生成器,自动生成数据主键(键生成器默认不开启)
objectStore = db.createObjectStore('yourStoreName', { autoIncrement: true });
};
自定义keyPath
键生成器
生成主键Key
2、删除数据
// 1、创建事务
const transaction = db.transaction([storeName], 'readwrite');
// 2、访问对象仓库
const store = transaction.objectStore(storeName);
// 3、根据keyPath或主键删除数据
store.delete(keyPath/key);
注:使用keyPath
进行删除时,传入的keyPath
一定要全等于(===)对象仓库的key
,否则会删除不成功。比如我想删除上图自定义keyPath
图中key为1688275751079
的数据,从图上能明显看到key为number,如果我写成delete('1688275751079')
执行后将会没有反应
更新数据库数据
// 1、创建事务
const transaction = db.transaction([storeName], 'readwrite');
// 2、访问对象仓库
const store = transaction.objectStore(storeName);
// 3、根据keyPath或主键修改数据,如果不存在keyPath/key,则新增该数据
store.put(newData);
例如:
// 根据keyPath修改数据
const newData = {
id: 1,
name: 'abc',
age: 23
};
store.put(newData); // newData中需要有一个对应到对象仓库数据的key,才能找到对应数据并修改
// 根据键生成器自动生成的主键更新数据
store.put(newData, key); // 第一个参数为新数据,第二个参数为对应到对象仓库数据的主键
获取数据库数据
const transaction = db.transaction([storeName], 'readwrite');
// 2、访问对象仓库
const store = transaction.objectStore(storeName);
// 3、根据keyPath或主键获取数据
const res = store.get(keyPath/key);
console.log(res.result);
资料参考:https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API