Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例

Web前端入门第 3 问:JavaScript 一个简单的 IndexedDB 数据库入门示例

一、什么是 IndexedDB?在Web开发中,我们经常需要在客户端存储数据。你可能已经熟悉了 localStorage 或 sessionStorage,但它们只能存储简单的字符串键值对,无法存储复杂的数据结构,而且存储容量有限(通常为5-10MB)。IndexedDB 是浏览器提供的一个本地数据库系统 ,它允许你在用户浏览器中存储大量结构化数据。与 localStorage 相比,IndexedDB 有以下优势:- 存储容量大 :通常可达几百MB甚至更多- 支持复杂数据结构 :可以存储对象、数组、二进制数据等- 支持索引和查询 :可以像 SQL 数据库一样进行条件查询- 异步操作 :不会阻塞页面渲染简单来说,IndexedDB 就是浏览器内置的"迷你数据库",特别适合离线应用、数据缓存等场景。## 二、核心概念在开始写代码之前,我们需要理解几个关键概念:1. 数据库(Database) :最顶层的容器,一个域名下可以创建多个数据库2. 对象仓库(Object Store) :类似于关系数据库中的"表",用于存储数据记录3. 索引(Index) :为对象仓库中的某个字段建立索引,方便快速查询4. 事务(Transaction) :所有读写操作都需要在事务中执行,确保数据一致性5. 游标(Cursor) :用于遍历对象仓库中的多条记录## 三、创建和打开数据库我们从一个最简单的示例开始:创建一个名为 "MyDatabase" 的数据库,并创建一个名为 "users" 的对象仓库。javascript// 步骤1:打开数据库const request = indexedDB.open("MyDatabase", 1);// 步骤2:处理打开失败的情况request.onerror = (event) => { console.error("数据库打开失败", event.target.error);};// 步骤3:处理打开成功的情况request.onsuccess = (event) => { const db = event.target.result; // 获取数据库实例 console.log("数据库打开成功!"); // 现在可以执行数据库操作了 // 但我们先关闭数据库,后面再详细操作 db.close();};// 步骤4:处理数据库版本升级(包括首次创建)request.onupgradeneeded = (event) => { const db = event.target.result; // 检查对象仓库是否已存在 if (!db.objectStoreNames.contains("users")) { // 创建对象仓库,并指定主键为 "id" const objectStore = db.createObjectStore("users", { keyPath: "id" }); // 为 "name" 字段创建索引,方便按名字查询 objectStore.createIndex("name", "name", { unique: false }); // 为 "email" 字段创建唯一索引 objectStore.createIndex("email", "email", { unique: true }); console.log("users 对象仓库创建成功!"); }};代码说明 :- indexedDB.open() 的第一个参数是数据库名称,第二个参数是版本号- onupgradeneeded 事件会在数据库首次创建或版本号变更时触发- keyPath 指定用哪个字段作为主键,类似 SQL 中的 PRIMARY KEY- 索引的 unique 参数表示是否允许重复值## 四、添加数据有了数据库结构后,我们来添加一些用户数据。javascript// 假设我们已经成功打开了数据库,db 是数据库实例function addUser(db, userData) { // 1. 创建一个事务,指定要操作的对象仓库和操作模式 // "readwrite" 表示读写模式 const transaction = db.transaction(["users"], "readwrite"); // 2. 获取对象仓库 const objectStore = transaction.objectStore("users"); // 3. 添加数据 const request = objectStore.add(userData); // 4. 处理成功/失败 request.onsuccess = (event) => { console.log("用户数据添加成功,主键为:", event.target.result); }; request.onerror = (event) => { console.error("添加用户失败:", event.target.error); }; // 5. 事务完成后的回调 transaction.oncomplete = () => { console.log("事务已完成"); };}// 调用示例:添加一个用户const user = { id: 1, name: "张三", email: "zhangsan@example.com", age: 25, createTime: new Date().toISOString()};// 注意:这里假设 db 是之前打开的数据库实例// 实际使用时需要确保 db 是有效的addUser(db, user);代码说明 :- 每次操作都需要先创建事务 transaction- add() 方法用于添加新记录,如果主键已存在会报错- 如果想更新已存在的记录,可以使用 put() 方法## 五、查询数据### 5.1 通过主键查询javascriptfunction getUserById(db, id) { // 创建只读事务 const transaction = db.transaction(["users"], "readonly"); const objectStore = transaction.objectStore("users"); // 通过主键获取数据 const request = objectStore.get(id); request.onsuccess = (event) => { const user = event.target.result; if (user) { console.log("找到用户:", user); } else { console.log("未找到该用户"); } }; request.onerror = (event) => { console.error("查询失败:", event.target.error); };}// 调用示例:查询 id 为 1 的用户getUserById(db, 1);### 5.2 通过索引查询javascriptfunction getUserByEmail(db, email) { const transaction = db.transaction(["users"], "readonly"); const objectStore = transaction.objectStore("users"); // 获取 "email" 索引 const index = objectStore.index("email"); // 通过索引值查询 const request = index.get(email); request.onsuccess = (event) => { const user = event.target.result; if (user) { console.log("通过邮箱找到用户:", user); } else { console.log("未找到该邮箱对应的用户"); } };}// 调用示例getUserByEmail(db, "zhangsan@example.com");### 5.3 获取所有数据(使用游标)javascriptfunction getAllUsers(db) { const transaction = db.transaction(["users"], "readonly"); const objectStore = transaction.objectStore("users"); // 创建游标,遍历所有记录 const request = objectStore.openCursor(); const users = []; request.onsuccess = (event) => { const cursor = event.target.result; if (cursor) { // 将当前记录添加到数组 users.push(cursor.value); // 移动到下一条记录 cursor.continue(); } else { // 遍历完成 console.log("所有用户:", users); } };}// 调用示例getAllUsers(db);## 六、更新和删除数据### 6.1 更新数据javascriptfunction updateUser(db, id, newData) { const transaction = db.transaction(["users"], "readwrite"); const objectStore = transaction.objectStore("users"); // 先获取原数据 const getRequest = objectStore.get(id); getRequest.onsuccess = (event) => { const user = event.target.result; if (!user) { console.log("用户不存在,无法更新"); return; } // 合并新数据 const updatedUser = { ...user, ...newData }; // 使用 put 方法更新(如果主键存在则更新,不存在则新增) const putRequest = objectStore.put(updatedUser); putRequest.onsuccess = () => { console.log("用户更新成功"); }; };}// 调用示例:更新年龄updateUser(db, 1, { age: 26 });### 6.2 删除数据javascriptfunction deleteUser(db, id) { const transaction = db.transaction(["users"], "readwrite"); const objectStore = transaction.objectStore("users"); const request = objectStore.delete(id); request.onsuccess = () => { console.log("用户删除成功"); }; request.onerror = (event) => { console.error("删除失败:", event.target.error); };}// 调用示例deleteUser(db, 1);## 七、完整示例下面是一个完整的示例,展示如何从打开数据库到增删改查的全过程:javascript// 完整示例:一个简单的用户管理系统function initDatabase() { return new Promise((resolve, reject) => { const request = indexedDB.open("UserDatabase", 1); request.onupgradeneeded = (event) => { const db = event.target.result; if (!db.objectStoreNames.contains("users")) { const store = db.createObjectStore("users", { keyPath: "id", autoIncrement: true }); store.createIndex("name", "name", { unique: false }); store.createIndex("email", "email", { unique: true }); } }; request.onsuccess = (event) => { resolve(event.target.result); }; request.onerror = (event) => { reject(event.target.error); }; });}// 使用示例async function main() { try { const db = await initDatabase(); console.log("数据库初始化成功"); // 添加用户 const user = { name: "李四", email: "lisi@example.com", age: 30 }; const transaction = db.transaction(["users"], "readwrite"); const store = transaction.objectStore("users"); store.add(user); // 查询所有用户 const allUsers = await new Promise((resolve) => { const users = []; const cursorRequest = store.openCursor(); cursorRequest.onsuccess = (event) => { const cursor = event.target.result; if (cursor) { users.push(cursor.value); cursor.continue(); } else { resolve(users); } }; }); console.log("所有用户:", allUsers); } catch (error) { console.error("操作失败:", error); }}main();## 八、总结通过本文的学习,我们掌握了 IndexedDB 的核心用法:1. 数据库操作 :使用 indexedDB.open() 创建或打开数据库2. 对象仓库管理 :在 onupgradeneeded 事件中创建和配置对象仓库3. 数据增删改查 :通过事务进行数据的添加、查询、更新和删除4. 索引查询 :利用索引实现高效的条件查询5. 游标遍历:使用游标处理多条记录IndexedDB 虽然 API 看起来复杂,但它的设计模式非常清晰:先打开数据库 → 创建对象仓库 → 通过事务执行操作。只要掌握这个流程,你就能轻松地在浏览器中存储和管理复杂数据。在实际项目中,你可以将 IndexedDB 用于:- 离线 Web 应用的本地数据存储- 缓存服务器返回的 API 数据- 保存用户配置和偏好设置- 存储大型文件或媒体资源希望这篇文章能帮助你迈出 IndexedDB 学习的第一步!

相关推荐
独行侠影a2 小时前
APScheduler+Redis 分布式定时任务:解决多实例任务重复执行
数据库·redis·分布式
kyriewen2 小时前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
传说故事2 小时前
数据库中一些常用英文单词含义
数据库·oracle
IT_陈寒2 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端
夏贰四2 小时前
中小企业搭建业务中台如何控成本?业务中台轻量化落地分几步实施?
数据库·业务中台
Revolution613 小时前
React 组件重新渲染时,到底重新执行了什么
前端·react.js·面试
林焱RPA3 小时前
影刀RPA200篇纪念版:最实用的20个自动化场景大盘点
数据库
名字还没想好☜3 小时前
Go 的 time.After 在 select 循环里内存泄漏:定时器堆积原理与 timer.Reset 正确姿势
java·数据库·golang·go·goroutine
用户2181697049304 小时前
Flutter(四)Dart语法 空安全 运算符 流程控制
前端