IndexedDB 是浏览器内置支持事务的 NoSQL 本地数据库,基于对象存储和索引机制,可离线持久化结构化数据;需通过 indexedDB.open() 创建连接并用 onupgradeneeded 管理 schema,所有读写操作必须在事务中进行,并可通过索引实现高效条件查询。

IndexedDB 是浏览器内置的、支持事务的 NoSQL 本地数据库,适合在前端持久化结构化数据(如对象、数组),无需后端即可离线使用。它不是“键值对”那么简单(像 localStorage),而是基于对象存储(Object Store)和索引机制,能高效查询、增删改查大量数据。
创建数据库并打开连接
IndexedDB 的操作必须通过 indexedDB.open() 启动,它返回一个请求对象,需监听 success/error 事件。版本号控制结构变更——升级时用 onupgradeneeded 创建/修改 objectStore。
- 首次打开或版本号升高时触发
onupgradeneeded,此时才能新建或修改 objectStore(类似建表) - 成功后在
onsuccess中拿到event.target.result(即 IDBDatabase 实例),后续所有操作都基于它 - 推荐封装成 Promise,避免回调嵌套:
const req = indexedDB.open(name, version);
req.onerror = () => reject(req.error);
req.onsuccess = () => resolve(req.result);
req.onupgradeneeded = (e) => {
const db = e.target.result;
if (!db.objectStoreNames.contains('users')) {
db.createObjectStore('users', { keyPath: 'id', autoIncrement: true });
}
};
});
增删改查:用事务和 objectStore 操作数据
所有读写必须在事务(IDBTransaction)中进行,事务作用域可限定为单个或多个 objectStore。读操作可用只读事务,写操作必须用 readwrite。
-
添加数据:获取 objectStore → 调用
add()或put()(put 可更新,add 拒绝重复主键) -
查询单条:用
get(key)(主键查找)或getKey(key) -
范围查询:用
getAll()或openCursor()配合 IDBKeyRange(如IDBKeyRange.lowerBound(10)) -
删除:用
delete(key)
return new Promise((resolve, reject) => {
const tx = db.transaction('users', 'readwrite');
const store = tx.objectStore('users');
const req = store.add(data);
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
};
添加索引支持条件查询
仅靠主键(keyPath)只能按 ID 查找。要按其他字段(如 email、createdAt)快速检索,需在 objectStore 上建立索引。
立即学习“Java免费学习笔记(深入)”;
- 索引在
onupgradeneeded中创建,指定字段名和唯一性(unique: true/false) - 查询时用
index.get(value)或index.getAll(),比遍历快得多 - 例如:给 users 添加 email 索引后,就能直接查
store.index('email').get('a@b.com')
store.createIndex('email', 'email', { unique: true });
store.createIndex('age', 'age', { unique: false });
}
错误处理与兼容性注意点
IndexedDB 行为在不同浏览器中基本一致,但仍有细节差异,需主动防御。
- 用户禁用或隐私模式下可能抛出
SecurityError或直接不可用,建议兜底用 localStorage - 事务自动提交,但若未监听 error 事件,失败会静默;务必监听
transaction.oncomplete / onerror - 主键不能为 undefined 或 null;autoIncrement 时不要手动设 keyPath 字段
- 大数据量插入建议分批 + requestIdleCallback 控制节奏,避免阻塞 UI


















