HTML5 入门教程
IndexedDB 客户端数据库
本教程共 110 篇 · 第 89 篇 · 更新于 2026-07-28 · 约 5 分钟阅读
HTML5HTML5 入门教程IndexedDBNoSQL客户端数据库事务
89. IndexedDB 客户端数据库
本节目标:理解 IndexedDB 是什么,知道它和 localStorage 的区别,能写出最基础的打开数据库和增删改查代码。
什么是 IndexedDB
localStorage 存的是字符串键值对,数据量大了就力不从心。IndexedDB 是浏览器内置的真正的数据库。
特点:
- 键值对存储:可以存对象、数组、文件等复杂数据
- 事务支持:操作要么全成功要么全失败,数据不会乱
- 异步 API:不阻塞页面渲染
- 容量大:一般是可用硬盘空间的百分比,比 localStorage 大得多
- 支持索引:可以按字段快速查询
NoteIndexedDB 是 NoSQL 数据库,没有 SQL 语句。所有操作通过 JavaScript API 完成。
和 localStorage 对比
| 对比项 | localStorage | IndexedDB |
|---|---|---|
| 数据模型 | 键值对(字符串) | 对象存储 |
| 容量 | ~5MB | 几百MB或更多 |
| API 复杂度 | 简单 | 较复杂 |
| 查询能力 | 只能按键查 | 支持索引和范围查询 |
| 同步/异步 | 同步 | 异步 |
| 适合场景 | 小配置项 | 大量结构化数据 |
打开(或创建)数据库
const request = indexedDB.open("MyDatabase", 1);
request.onsuccess = function (event) {
const db = event.target.result;
console.log("数据库打开成功");
};
request.onerror = function (event) {
console.error("打开失败", event.target.error);
};
第一个参数是数据库名,第二个是版本号。版本号变化时会触发升级。
创建对象存储和索引
数据库结构在 onupgradeneeded 里定义。类似建表:
request.onupgradeneeded = function (event) {
const db = event.target.result;
// 创建"对象存储"(类似表),id 作为主键
const store = db.createObjectStore("users", { keyPath: "id" });
// 创建索引,方便按 name 字段查询
store.createIndex("nameIndex", "name", { unique: false });
// 唯一索引:email 不能重复
store.createIndex("emailIndex", "email", { unique: true });
};
添加数据
function addUser(db, user) {
const transaction = db.transaction(["users"], "readwrite");
const store = transaction.objectStore("users");
const request = store.add(user);
request.onsuccess = function () {
console.log("添加成功,id:", request.result);
};
transaction.onerror = function () {
console.error("添加失败");
};
}
// 使用
addUser(db, { id: 1, name: "张三", email: "zhang@example.com" });
查询数据
按主键查:
function getUser(db, id) {
const transaction = db.transaction(["users"], "readonly");
const store = transaction.objectStore("users");
const request = store.get(id);
request.onsuccess = function () {
if (request.result) {
console.log("找到用户:", request.result);
} else {
console.log("没找到");
}
};
}
按索引查:
function getUserByName(db, name) {
const transaction = db.transaction(["users"], "readonly");
const store = transaction.objectStore("users");
const index = store.index("nameIndex");
const request = index.get(name);
request.onsuccess = function () {
console.log("查询结果:", request.result);
};
}
更新和删除
// 更新:put 会覆盖同名主键的记录
function updateUser(db, user) {
const transaction = db.transaction(["users"], "readwrite");
const store = transaction.objectStore("users");
store.put(user);
}
// 删除
function deleteUser(db, id) {
const transaction = db.transaction(["users"], "readwrite");
const store = transaction.objectStore("users");
store.delete(id);
}
完整示例
下面是一个可以打开浏览器控制台直接试的最小化示例:
// 打开数据库
const request = indexedDB.open("TestDB", 1);
request.onupgradeneeded = function (e) {
const db = e.target.result;
db.createObjectStore("books", { keyPath: "id" });
};
request.onsuccess = function (e) {
const db = e.target.result;
// 添加一本书
const tx = db.transaction(["books"], "readwrite");
tx.objectStore("books").add({ id: 1, title: "HTML5入门", author: "码上学" });
tx.oncomplete = function () {
// 查询这本书
const query = db.transaction(["books"]).objectStore("books").get(1);
query.onsuccess = function () {
console.log(query.result); // {id: 1, title: "HTML5入门", author: "码上学"}
};
};
};
TipIndexedDB 的 API 基于事件(event-based),不是 Promise。新手容易陷入回调地狱。实际项目中可以用
idb这样的轻量库,它把 IndexedDB 包装成了 Promise 风格,好用很多。
适用场景
- 离线应用:数据存在本地,断网也能用
- 缓存大量数据:比如文章列表、商品信息
- 存储文件/Blob:可以直接存图片、音视频的 Blob 对象
- 需要复杂查询:按日期范围、价格区间等条件筛选数据
WarningIndexedDB API 比较原始,新手可能觉得繁琐。如果数据量不大,localStorage 够用就别上 IndexedDB。需要复杂操作时考虑用
idb或Dexie.js这样的封装库。