核心特性
- NoSQL存储:自由存储结构化数据(支持JSON对象)
- 事务支持:ACID事务保证数据一致性
- 索引系统:支持多字段索引查询(最大支持256个索引)
- 异步API:所有操作不阻塞主线程
- 大容量:Chrome默认允许存储网站数据的60%(最高可达80%硬盘空间)
- 离线支持:PWA应用的核心存储方案
快速入门
生命周期管理
- 开启数据库:
indexedDB.open(name, version)
- 版本升级:在
onupgradeneeded中修改结构
- 对象仓库:类似SQL的表结构
- 事务操作:所有数据操作必须通过事务
核心对象关系
Database → ObjectStore → Index
↑
Transaction → Cursor
完整代码示例
1. 数据库初始化
const DB_NAME = 'userDB';
const STORE_NAME = 'userProfile';
const DB_VERSION = 3;
const dbRequest = indexedDB.open(DB_NAME, DB_VERSION);
dbRequest.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains(STORE_NAME)) {
const store = db.createObjectStore(STORE_NAME, {
keyPath: 'userId',
autoIncrement: false
});
store.createIndex('age_gender', ['age', 'gender'], { unique: false });
store.createIndex('email', 'email', { unique: true });
}
if (event.oldVersion < 2) {
const store = event.target.transaction.objectStore(STORE_NAME);
store.createIndex('lastLogin', 'loginTimestamp', { unique: false });
}
};
dbRequest.onsuccess = (event) => {
const db = event.target.result;
db.onversionchange = () => db.close();
};
2. 数据操作
事务封装方法
async function executeTransaction(db, storeNames, mode, operation) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeNames, mode);
transaction.oncomplete = () => resolve();
transaction.onerror = (e) => reject(e.target.error);
operation(transaction);
});
}
增删改查实现
async function bulkWrite(db, items) {
await executeTransaction(db, [STORE_NAME], 'readwrite', (tx) => {
const store = tx.objectStore(STORE_NAME);
items.forEach(item => store.put(item));
});
}
async function conditionalUpdate(db, userId, updates) {
const user = await getRecord(db, userId);
if (user.loginCount > 5) {
await updateRecord(db, { ...user, ...updates });
}
}
async function paginatedQuery(db, indexName, range, pageSize, pageNumber) {
return new Promise((resolve) => {
const transaction = db.transaction([STORE_NAME]);
const store = transaction.objectStore(STORE_NAME);
const index = store.index(indexName);
const results = [];
let count = 0;
let advanced = false;
index.openCursor(range).onsuccess = (event) => {
const cursor = event.target.result;
if (!cursor) return resolve(results);
if (!advanced && pageNumber > 1) {
cursor.advance((pageNumber - 1) * pageSize);
advanced = true;
return;
}
results.push(cursor.value);
if (++count >= pageSize) return resolve(results);
cursor.continue();
};
});
}
架构原理
存储结构
| 层级 | 说明 | 限制 |
|---|
| Database | 数据库容器 | 同源下可创建多个 |
| ObjectStore | 数据存储实体 | 每个DB最多300个 |
| Index | 索引加速查询 | 每个Store最多256个索引 |
| Cursor | 数据遍历迭代器 | 自动管理内存 |
事务模型
- 作用域:预定义ObjectStore集合
- 模式:readonly(默认) / readwrite / versionchange
- 自动提交:约1秒无操作自动提交
- 错误处理:事务中任一操作失败则整体回滚
浏览器兼容指南
支持矩阵
| 浏览器 | 支持版本 | 存储配额策略 |
|---|
| Chrome | 24+ | 按磁盘空间比例 |
| Firefox | 16+ | 独立于SQLite存储 |
| Safari | 8+ | 严格7天LRU清理策略 |
| Edge | 12+ | 继承IE10+实现 |
容量估算
navigator.storage.estimate().then(estimate => {
console.log(`可用空间:${estimate.quota / 1024 ** 2} MB`);
console.log(`已用空间:${estimate.usage / 1024 ** 2} MB`);
});
最佳实践场景
推荐场景
- 离线优先应用(如PWA)
- 客户端分析数据存储
- 富文本自动保存
- 媒体资源元数据管理
- 实时协作应用状态同步
性能对比
| 操作类型 | localStorage | IndexedDB |
|---|
| 10KB写入 | 0.2ms | 2ms |
| 10MB写入 | 阻塞 | 120ms |
| 条件查询 | 不可 | 8ms |
| 万级数据遍历 | 阻塞 | 45ms |
专家级技巧
高级优化
- 批量写入:合并操作减少事务开销
- 游标复用:使用advance()实现快速分页
- 内存管理:合理设置keyRange避免全表扫描
- 压缩策略:存储前使用JSON.stringify压缩
- Worker集成:将复杂操作移入Web Worker
调试技巧
indexedDB.databases().then(dbs =>
console.log('现有数据库:', dbs)
);
const start = performance.now();
transaction.oncomplete = () =>
console.log(`事务耗时:${performance.now() - start}ms`);
资源推荐
工具库
- idb:Promise封装库(2KB)
- Dexie.js:类ORM高级封装
- localForage:自动降级存储方案
调试工具
- Chrome DevTools IndexedDB面板
- Firedox Storage Inspector
- Safari Web Inspector
扩展阅读
通过本指南,您已掌握IndexedDB从基础到高级的完整知识体系。建议在实际项目中结合Service Worker和Cache API构建完整的离线解决方案。