IndexedDB 数据库详解 💾
背景 🎯
在前端开发中,当需要存储大量数据或二进制文件时,localStorage 的存储限制(通常为 5-10MB)往往无法满足需求。这时,IndexedDB 作为浏览器内置的低级 API 数据库,成为了最佳选择。
IndexedDB 核心特性 ⭐
1. 基础特性
- 📦 键值对存储: 使用对象仓库(object store)存储数据,支持所有类型数据
- 🔑 主键唯一: 每条数据都需要唯一主键标识
- ⚡ 异步操作: 所有操作都是异步的,不会阻塞主线程
- 🔄 事务机制: 支持事务操作,保证数据完整性
- 🌐 同源策略: 遵循浏览器同源策略,只能访问同域名下的数据库
- 💾 存储容量: 通常不少于 250MB,远超 localStorage
- 📄 数据类型: 支持存储 JavaScript 对象、ArrayBuffer、Blob 等多种类型
2. 使用场景 🎨
- 离线应用数据存储
- 大文件/二进制数据存储
- 客户端缓存
- 临时数据存储
实战指南 📝
1. 数据库操作基础
打开/创建数据库
javascript
const dbName = 'MyDatabase';
const version = 1;
const request = indexedDB.open(dbName, version);
request.onerror = (event) => {
console.error('数据库打开失败 ❌', event.target.error);
};
request.onsuccess = (event) => {
const db = event.target.result;
console.log('数据库打开成功 ✅');
};
request.onupgradeneeded = (event) => {
const db = event.target.result;
// 数据库升级或新建时的处理逻辑
};创建对象仓库
javascript
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 });
}
};2. 数据操作实用工具 🛠️
以下是一个实用的 IndexedDB 操作封装:
javascript
// 数据库操作类
class IndexedDBHelper {
static async openDB(dbName, storeName, version = 1) {
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, version);
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains(storeName)) {
db.createObjectStore(storeName, { autoIncrement: true });
}
};
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
static async putData(db, storeName, data) {
return new Promise((resolve, reject) => {
const transaction = db.transaction([storeName], 'readwrite');
const store = transaction.objectStore(storeName);
const request = store.put(data);
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
static async getData(db, storeName, key) {
return new Promise((resolve, reject) => {
const transaction = db.transaction([storeName], 'readonly');
const store = transaction.objectStore(storeName);
const request = store.get(key);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
}最佳实践与注意事项 ⚠️
版本控制
- 每次修改数据库结构时都要更新版本号
- 在 onupgradeneeded 中处理版本升级逻辑
错误处理
- 始终添加错误处理逻辑
- 使用 try-catch 包装异步操作
性能优化
- 批量操作时使用同一个事务
- 适当使用索引提升查询性能
存储限制
- 定期清理不需要的数据
- 监控存储空间使用情况
示例应用 🌟
javascript
// 实际应用示例:存储用户上传的图片
async function saveUserImage(imageBlob) {
try {
const db = await IndexedDBHelper.openDB('ImageDB', 'images');
await IndexedDBHelper.putData(db, 'images', {
timestamp: Date.now(),
data: imageBlob
});
console.log('图片保存成功 ✅');
} catch (error) {
console.error('图片保存失败 ❌', error);
}
}总结 📚
IndexedDB 是一个功能强大的客户端存储解决方案,特别适合处理大量结构化数据。通过合理使用其事务和索引特性,可以构建高性能的离线应用。记住要处理好错误情况,并遵循最佳实践来优化应用性能。