前端 IndexedDB 详细教程

IndexedDB 是一个浏览器内置的 NoSQL 数据库系统,允许在客户端存储大量结构化数据,并支持高性能搜索。相比 localStorage,IndexedDB 更适合存储大量数据并提供更复杂的查询功能。

基本概念

  1. 数据库:每个源(协议+域名+端口)可以创建多个数据库
  2. 对象存储(Object Store):类似于数据库中的表
  3. 索引(Index):用于快速查找数据
  4. 事务(Transaction):所有操作必须在事务中执行
  5. 游标(Cursor):用于遍历对象存储中的数据

打开/创建数据库

const request = indexedDB.open('myDatabase', 1);request.onerror = function(event) {console.error("数据库打开失败:", event.target.error);
};request.onsuccess = function(event) {const db = event.target.result;console.log("数据库打开成功");// 在这里执行数据库操作
};request.onupgradeneeded = function(event) {const db = event.target.result;// 创建对象存储和索引if (!db.objectStoreNames.contains('customers')) {const store = db.createObjectStore('customers', { keyPath: 'id' });// 创建索引store.createIndex('name', 'name', { unique: false });store.createIndex('email', 'email', { unique: true });}
};

添加数据

function addCustomer(db, customer) {const transaction = db.transaction(['customers'], 'readwrite');const store = transaction.objectStore('customers');const request = store.add(customer);request.onsuccess = function() {console.log('数据添加成功');};request.onerror = function(event) {console.error('数据添加失败:', event.target.error);};
}// 使用示例
const db = /* 获取数据库实例 */;
addCustomer(db, {id: 1,name: '张三',email: 'zhangsan@example.com',age: 30
});

读取数据

通过主键读取

function getCustomer(db, id) {const transaction = db.transaction(['customers'], 'readonly');const store = transaction.objectStore('customers');const request = store.get(id);request.onsuccess = function() {const customer = request.result;if (customer) {console.log('找到客户:', customer);} else {console.log('未找到客户');}};request.onerror = function(event) {console.error('读取数据失败:', event.target.error);};
}

通过索引读取

function getCustomerByName(db, name) {const transaction = db.transaction(['customers'], 'readonly');const store = transaction.objectStore('customers');const index = store.index('name');const request = index.get(name);request.onsuccess = function() {const customer = request.result;console.log('找到客户:', customer);};request.onerror = function(event) {console.error('通过索引查询失败:', event.target.error);};
}

更新数据

function updateCustomer(db, customer) {const transaction = db.transaction(['customers'], 'readwrite');const store = transaction.objectStore('customers');const request = store.put(customer);request.onsuccess = function() {console.log('数据更新成功');};request.onerror = function(event) {console.error('数据更新失败:', event.target.error);};
}

删除数据

function deleteCustomer(db, id) {const transaction = db.transaction(['customers'], 'readwrite');const store = transaction.objectStore('customers');const request = store.delete(id);request.onsuccess = function() {console.log('数据删除成功');};request.onerror = function(event) {console.error('数据删除失败:', event.target.error);};
}

使用游标遍历数据

function getAllCustomers(db) {const transaction = db.transaction(['customers'], 'readonly');const store = transaction.objectStore('customers');const request = store.openCursor();const customers = [];request.onsuccess = function(event) {const cursor = event.target.result;if (cursor) {customers.push(cursor.value);cursor.continue();} else {console.log('所有客户:', customers);}};request.onerror = function(event) {console.error('遍历数据失败:', event.target.error);};
}

高级用法

使用索引范围查询

function getCustomersByAgeRange(db, min, max) {const transaction = db.transaction(['customers'], 'readonly');const store = transaction.objectStore('customers');// 假设我们创建了age索引const index = store.index('age');const range = IDBKeyRange.bound(min, max);const request = index.openCursor(range);const customers = [];request.onsuccess = function(event) {const cursor = event.target.result;if (cursor) {customers.push(cursor.value);cursor.continue();} else {console.log('年龄范围内的客户:', customers);}};
}

批量操作

function addMultipleCustomers(db, customers) {const transaction = db.transaction(['customers'], 'readwrite');const store = transaction.objectStore('customers');customers.forEach(customer => {store.add(customer);});transaction.oncomplete = function() {console.log('批量添加完成');};transaction.onerror = function(event) {console.error('批量操作失败:', event.target.error);};
}

数据库版本管理

// 升级数据库版本
function upgradeDB() {const request = indexedDB.open('myDatabase', 2); // 版本号增加request.onupgradeneeded = function(event) {const db = event.target.result;const oldVersion = event.oldVersion;const newVersion = event.newVersion;// 从版本1升级到版本2if (oldVersion < 1) {// 初始创建逻辑}if (oldVersion < 2) {// 版本2的变更if (!db.objectStoreNames.contains('orders')) {const store = db.createObjectStore('orders', { keyPath: 'orderId' });store.createIndex('customerId', 'customerId', { unique: false });}}};
}

最佳实践

  1. 错误处理:始终处理onerror事件
  2. 事务管理:合理使用事务,避免长时间持有事务
  3. 性能优化:对于大量数据操作,使用游标分批处理
  4. 内存管理:处理完数据后关闭游标和数据库连接
  5. 兼容性:检查浏览器支持情况
if (!window.indexedDB) {console.error("您的浏览器不支持IndexedDB");
}

封装示例

class IndexedDBWrapper {constructor(dbName, version) {this.dbName = dbName;this.version = version;this.db = null;}open() {return new Promise((resolve, reject) => {const request = indexedDB.open(this.dbName, this.version);request.onerror = (event) => reject(event.target.error);request.onsuccess = (event) => {this.db = event.target.result;resolve(this.db);};request.onupgradeneeded = (event) => {const db = event.target.result;if (!db.objectStoreNames.contains('data')) {const store = db.createObjectStore('data', { keyPath: 'id' });store.createIndex('timestamp', 'timestamp', { unique: false });}};});}add(storeName, data) {return new Promise((resolve, reject) => {const transaction = this.db.transaction([storeName], 'readwrite');const store = transaction.objectStore(storeName);const request = store.add(data);request.onsuccess = () => resolve(request.result);request.onerror = (event) => reject(event.target.error);});}// 其他方法类似封装...
}// 使用示例
(async function() {const dbWrapper = new IndexedDBWrapper('myAppDB', 1);try {await dbWrapper.open();await dbWrapper.add('data', { id: 1, value: 'test', timestamp: Date.now() });console.log('操作成功');} catch (error) {console.error('操作失败:', error);}
})();

IndexedDB 提供了强大的客户端存储能力,适合需要离线功能或处理大量结构化数据的 Web 应用。通过合理使用,可以显著提升应用性能和用户体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/910394.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/910394.shtml
英文地址,请注明出处:http://en.pswp.cn/news/910394.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

扩散模型与强化学习(1):字节Seedance中的人类偏好优化实践

扩散模型与强化学习(0)&#xff1a;专栏汇总与导航 前言&#xff1a;最近强化学习在Diffusion Models得到了越来越多广泛的应用&#xff0c;本专栏将系统性地介绍当前Diffusion Models中实用且前沿的技术进展。这篇博客介绍字节最新的视频生成模型Seedance 1.0: Exploring the …

【内存】Linux 内核优化实战 - vm.max_map_count

目录 vm.max_map_count参数全面解析一、参数定义与核心作用二、默认值与关键调整场景1. 默认限制与不足场景2. 典型报错案例 三、操作指南&#xff1a;查看与修改方法四、场景化建议值与配置示例五、关键注意事项六、延伸知识&#xff1a;内存映射的底层逻辑 vm.max_map_count参…

组件之间的双向绑定:v-model

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…

GetX 实现 MVVM 架构, 高效 路由管理 和 状态管理

GetX是Flutter中的一个高效的状态管理与路由管理框架&#xff0c;结合MVVM架构能简化代码逻辑。以下是使用GetX实现MVVM架构&#xff0c;并完成路由和状态管理的核心思路与实践&#xff1a; 一、MVVM架构在GetX中的映射 MVVM&#xff08;Model-View-ViewModel&#xff09;与G…

Qt项目,记事本

一、项目说明 项目功能&#xff1a; &#xff08;1&#xff09;打开文件&#xff1a;点击打开文件按钮弹出对话框&#xff0c;选择文本文件后&#xff0c;在主窗口编辑界面显示内容。 &#xff08;2&#xff09;关闭文件&#xff1a;关闭打开的文件&#xff0c;并询问是否保存…

【全开源】填表问卷统计预约打卡表单系统+uniapp前端

一.系统介绍 填表问卷统计预约打卡表单系统是ThinkPHPUniApp开发的一款集信息填表、预约报名&#xff0c;签到打卡、活动通知、报名投票、班级统计等功能的自定义表单统计小程序。 二.搭建环境 系统环境&#xff1a;CentOS、 运行环境&#xff1a;宝塔 Linux 网站环境&…

开源 python 应用 开发(一)python、pip、pyAutogui、python opencv安装

最近有个项目需要做视觉自动化处理的工具&#xff0c;最后选用的软件为python&#xff0c;刚好这个机会进行系统学习。短时间学习&#xff0c;需要快速开发&#xff0c;所以记录要点步骤&#xff0c;防止忘记。 链接&#xff1a; 开源 python 应用 开发&#xff08;一&#x…

SpringCloud + Zookeeper + Feign整合及Feign原理

知其然 SpringCloud Zookeeper Spring Cloud 与 Zookeeper的整合只需要添加相关的starter依赖和增加相关注解即可完成。 pom.xml 如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.…

深入探索 OpenCV 图像识别:从基础到深度学习

在当今数字化时代&#xff0c;图像识别技术已经渗透到我们生活的方方面面&#xff0c;从智能手机中的拍照翻译功能到自动驾驶汽车的目标检测系统&#xff0c;图像识别的应用无处不在。作为一名算法工程师&#xff0c;我有幸深入研究并实践了 OpenCV 在图像识别领域的强大功能。…

Hadoop部署(HA)高可用集群

一、准备工作 1.把集群全部停掉 在三台节点上都做&#xff08;在xshell通过右键----> 发送输入到--->所有会话&#xff09; 2..在/export/servers下创建HA目录 sudo mkdir -p /export/servers/HA 3.创建用户和设置所属主和所属组 #创建用户 sudo adduser ygre #设置…

STM32 CAN位同步、错误处理

一、接收方数据采样 CAN总线没有时钟线&#xff0c;总线上的所有设备通过约定波特率的方式确定每一个数据位的时长发送方以约定的位时长每隔固定时间输出一个数据位接收方以约定的位时长每隔固定时间采样总线的电平&#xff0c;输入一个数据位理想状态下&#xff0c;接收方能依…

django serializer __all__中 额外添加外键里的某一个属性

在Django中使用序列化器&#xff08;Serializer&#xff09;时&#xff0c;你可能会遇到需要将模型&#xff08;Model&#xff09;中的外键字段转换成其关联对象的一部分属性的情况。默认情况下&#xff0c;序列化器会自动序列化外键字段&#xff0c;但如果你想要在序列化结果中…

Redis快的原因

Redis 高性能的核心原因 Redis 之所以能达到极高的性能&#xff08;10万 QPS&#xff09;&#xff0c;主要源于以下几个关键设计&#xff1a; 1. 纯内存操作 核心优势&#xff1a;所有数据存储在内存中&#xff0c;避免了磁盘 I/O 瓶颈 内存访问速度比磁盘快 10万倍以上&am…

【大模型微调】6.模型微调实测与格式转换导出

引言 本文继续研究 LLaMA-Factory 微调数据的流程&#xff0c;侧重于微调结果与模型导出。 数据集准备 首先参考 LLaMA-Factory 核心开发者的文章[1]&#xff0c;下载用于微调的公开的商品文案数据集 AdvertiseGen。 下载地址&#xff1a;https%3A//cloud.tsinghua.edu.cn/…

3085. 成为 K 特殊字符串需要删除的最少字符数

3085. 成为 K 特殊字符串需要删除的最少字符数 给你一个字符串 word 和一个整数 k。 如果 |freq(word[i]) - freq(word[j])| < k 对于字符串中所有下标 i 和 j 都成立&#xff0c;则认为 word 是 k 特殊字符串。 此处&#xff0c;freq(x) 表示字符 x 在 word 中的出现频…

分布式系统中的 Kafka:流量削峰与异步解耦(二)

Kafka 在分布式系统中的应用案例 电商订单系统 在电商领域&#xff0c;订单系统是核心业务模块之一&#xff0c;涉及多个复杂的业务环节和系统组件之间的交互。以常见的电商购物流程为例&#xff0c;当用户在电商平台上下单后&#xff0c;订单创建服务会首先接收到用户的订单…

从事登高架设作业需要注意哪些安全事项?

从事登高架设作业&#xff08;如脚手架搭设、高空维修、外墙清洗等&#xff09;属于高风险特种作业&#xff0c;必须严格遵守安全规范。以下是关键安全注意事项&#xff0c;涵盖作业前准备、作业中操作、应急处理三大环节&#xff0c;符合国家《高处作业安全技术规范》&#xf…

RA4M2开发IOT(6)----涂鸦模组快速上云

RA4M2开发IOT.6--涂鸦模组快速上云 概述视频教学样品申请硬件准备参考程序涂鸦官网链接创建一个项目选择对应产品产品基本配置添加标准功能APP界面配置硬件选择产品配置硬件详情PCB原理图涂鸦调试文件下载进入调试涂鸦模块串口协议心跳检测查询产品信息查询工作模式AP配网APP链…

AI时代SEO关键词革新

内容概要 在人工智能&#xff08;AI&#xff09;技术快速发展的背景下&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;关键词策略正经历根本性变革。本文将系统阐述AI如何重塑关键词研究、优化及效果评估的全流程。具体而言&#xff0c;首先解析智能研究方法在挖掘用户意…

JavaEE初阶第三期:解锁多线程,从 “单车道” 到 “高速公路” 的编程升级(一)

专栏&#xff1a;JavaEE初阶起飞计划 个人主页&#xff1a;手握风云 目录 一、认识线程 1.1. 概念 1.2. 为什么要使用线程 1.3. 进程和线程的关系 1.4. 多线程模型 二、多线程的创建 2.1. 继承Thread类 2.2. 实现Runnable接口 2.3. 匿名内部类 2.4. lambda表达式 一、…