网站首页 > 技术文章 正文
往期回顾
在之前的文章中,我们介绍了IndexDB vs Cookies vs Session这几个的对比,但是没有做实际项目的演示,今天我们用实际项目来演示IndexDB的便捷性。
往期文章:前端进阶必备:IndexDB 与 Cookies、Session 全解析及 IndexDB 入门指南-CSDN博客
首先需要明确的是IndexDB的适用场景:
- 离线应用
- 大型网页游戏
- 数据缓存
- 复杂数据管理和查询
项目实战
我们用纯IndexDB来实现表格的基本增删改查的功能!
这只是一个引子,实际上你可以将本示例的思想用于更大的场景
初始化表
按如下代码格式初始化IndexDB,如果初始不存在,则创建表CryptSetting(实际名称可自定义)和表的字段名,如下objectStore.createIndex()方法。
创建表是最好声明一个自增的唯一主键id,本例为projectId
let db = null;
// 初始化indexDB数据库
async function initDB() {
const request = window.indexedDB.open('CryptSetting', 1);
// success 事件表示成功打开数据库
request.onsuccess = (event) => {
db = event.target.result;
// 打开成功之后需要获取数据库列表
getList()
};
// error 事件表示打开数据库失败
request.onerror = (event) => {
console.log('打开 IndexedDB 失败');
};
// 如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件 upgradeneeded
request.onupgradeneeded = function (e) {
db = e.target.result;
let objectStore;
if ( !db.objectStoreNames.contains('CryptSetting') ) {
// 索引名称、索引所在的属性、配置对象(说明该属性是否包含重复的值)
objectStore = db.createObjectStore('CryptSetting', { keyPath: 'projectId', autoIncrement: true });
objectStore.createIndex('project_name', 'projectName', { unique: false });
objectStore.createIndex('key_1', 'key', { unique: false });
objectStore.createIndex('iv_1', 'iv', { unique: false });
}
};
}
初始化之后,会在控制台看到如下:
获取列表
初始化之后,需要获取数据库列表
请注意以下的写法,列表只能一条条获取,可以先声明一个空数组接收,最后统一赋值
此处用到了continue方法
效率还是很快的,不要以为一条条获取速度就慢!
// 获取配置列表
async function getList() {
loading.value = true
const transaction = db.transaction([ 'CryptSetting' ], 'readonly');
const objectStore = transaction.objectStore('CryptSetting');
const request = objectStore.openCursor(); // 获取所有配置
// indexDB是一个个获取数据的,所以用数组接收,最后统一赋值
const tempArr = []
request.onsuccess = function (event) {
const cursor = event.target.result;
if (cursor) {
tempArr.push(cursor.value);
cursor.continue(); // 继续遍历下一条数据
} else {
tableData.value = tempArr
loading.value = false
}
};
request.onerror = function () {
errorTip('获取列表失败')
loading.value = false
};
}
新增表的数据项
表初始化之后,其实还是空的表,所以上面获取值为空,所以此时需要往里面添加数据,按如下格式写即可。
注意:此处不传projectId,因为它是主键ID、会自动生成,按123456,
如果6被删除了,下次自动生成的ID为7
function addSettings() {
const transaction = db.transaction([ 'CryptSetting' ], 'readwrite');
const objectStore = transaction.objectStore('CryptSetting');
const { projectName, key, iv } = formData.value // 此处不传projectId,自动生成
const request = objectStore.add({
projectName,
key,
iv
});
request.onsuccess = function (event) {
successTip('添加成功')
};
request.onerror = function (event) {
errorTip()
};
}
新增之后,效果如下:
获取详情
根据ID获取详情
// 获取配置详情
function getSettingsDetail(id) {
const transaction = db.transaction([ 'CryptSetting' ], 'readonly');
const objectStore = transaction.objectStore('CryptSetting');
const request = objectStore.get(id);
request.onsuccess = function (event) {
const result = event.target.result;
if (result) {
title.value = '编辑项目配置'
isEdit.value = true
dialogVisible.value = true
formData.value = result
} else {
errorTip('获取失败')
}
};
request.onerror = function(event) {}
}
根据其他字段获取详情
在 IndexedDB 中,get 方法只能根据主键(keyPath)来查询数据。如果你需要根据其他字段(如 projectName、key、iv 等)来查询数据,可以使用索引(index)。索引允许你根据非主键字段来查询数据。
以下示例为:根据 projectName 查询配置详情
function getSettingsByProjectName(projectName) {
console.log('projectName', projectName);
const transaction = db.transaction(['CryptSetting'], 'readonly');
const objectStore = transaction.objectStore('CryptSetting');
const index = objectStore.index('project_name');
const request = index.get(projectName);
request.onsuccess = function (event) {
const result = event.target.result;
if (result) {
title.value = '编辑项目配置';
isEdit.value = true;
dialogVisible.value = true;
formData.value = result;
} else {
errorTip('获取失败');
}
};
request.onerror = function (event) {
console.error('查询失败', event);
errorTip('查询失败');
};
}
删除数据
// 删除配置,传参id
function deleteSettings(id) {
const transaction = db.transaction([ 'CryptSetting' ], 'readwrite');
const objectStore = transaction.objectStore('CryptSetting');
const request = objectStore.delete(id); // 假设我们要删除id的记录
request.onsuccess = function (event) {
successTip('删除成功');
};
request.onerror = function (event) {
errorTip('删除失败');
};
}
总结
IndexDB的许多思想都和mysql有相似之处。
我们发现,基本上增删改查都有相似的代码
const transaction = db.transaction(['CryptSetting'], 'readwrite');
const objectStore = transaction.objectStore('CryptSetting');
其实这段代码是不能省略的,因为它:
- 事务的独立性:每个事务都是独立的,不能共享。一旦事务完成,就不能再使用它。如果尝试在多个操作中重用同一个事务,会导致错误。
- 数据一致性:每个事务确保数据的一致性。如果多个操作共享同一个事务,一个操作失败会导致整个事务回滚,影响其他操作。
- 错误隔离:每个事务有自己的错误处理机制。如果一个事务失败,其他事务不会受到影响。通过每次操作声明新的事务,可以更好地控制错误处理和回滚。
为了确保数据操作的正确性和一致性,每次进行新增、删除、更新等操作时都需要声明新的 transaction 和 objectStore。这是 IndexedDB 的设计原则,确保每个操作都是独立且可靠的。因此,不能省略每次操作时的 transaction 和 objectStore 声明。
以上仅为简易的入门,及细节讲解,更多细节需要实战中探索,感谢观看,如有误请指正!
- 上一篇: 一文读懂用户权限设计
- 下一篇: 前端缓存总结-HTTP缓存
猜你喜欢
- 2025-01-12 CDN+OpenResty 实现丝滑访问的登录态缓存站
- 2025-01-12 如何在Spring Boot中通过布隆过滤器防止缓存穿透问题?
- 2025-01-12 HTML5缓存机制浅析:移动端Web加载性能优化
- 2025-01-12 如何在 NGINX 中缓存内容
- 2025-01-12 如何解决服务器缓存过高
- 2025-01-12 白帽黑客贡献新的Web攻击方式,CDN缓存服务器成为数据泄露目标
- 2025-01-12 西部数据推出新款蓝盘机械硬盘:CMR技术,4TB 549元
- 2025-01-12 面试官:如何实现多级缓存?
- 2025-01-12 基于spring boot的注解缓存,自带轻量级缓存管理系统
- 2025-01-12 系统设计 | 缓存系统设计
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端md5加密 (49)
- 前端路由 (55)
- 前端数组 (65)
- 前端定时器 (47)
- 前端接口 (46)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle约束 (46)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- mac oracle (47)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)