**基本概念**
1. **数据库(Database)**
最高级别的存储容器,包含多个对象存储空间(Object Store)。
2. **对象存储空间(Object Store)**
类似于关系型数据库中的表,用于存储一组对象。每个对象必须有一个唯一的键(key)。
3. **事务(Transaction)**
所有数据操作(增删改查)都必须在事务中进行,确保数据的一致性。
4. **索引(Index)**
用于加速数据查询,可基于对象的某个属性创建索引。
**核心 API 与流程**
IndexedDB 使用异步操作,主要通过 **promise** 或 **事件监听** 处理结果。
**1. 打开数据库**
javascript
const request = indexedDB.open('MyDatabase', 1); // 数据库名, 版本号
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;
// 创建对象存储空间(类似创建表)
const store = db.createObjectStore('Users', {
keyPath: 'id', // 对象的哪个属性作为主键
autoIncrement: true // 自动生成主键
});
// 创建索引(可选)
store.createIndex('nameIndex', 'name', { unique: false });
store.createIndex('ageIndex', 'age', { unique: false });
};
**2. 添加数据**
javascript
function addUser(db, user) {
const transaction = db.transaction(['Users'], 'readwrite');
const store = transaction.objectStore('Users');
const request = store.add(user);
request.onsuccess = () => {
console.log('数据添加成功');
};
request.onerror = (event) => {
console.error('数据添加失败:', event.target.error);
};
}
// 使用示例
addUser(db, { name: 'Alice', age: 30 });
addUser(db, { name: 'Bob', age: 25 });
**3. 查询数据**
javascript
// 通过主键查询
function getUserById(db, id) {
const transaction = db.transaction(['Users']);
const store = transaction.objectStore('Users');
const request = store.get(id);
request.onsuccess = (event) => {
console.log('查询结果:', event.target.result);
};
}
// 使用索引查询
function getUsersByAge(db, age) {
const transaction = db.transaction(['Users']);
const store = transaction.objectStore('Users');
const index = store.index('ageIndex'); // 使用之前创建的索引
const request = index.getAll(age);
request.onsuccess = (event) => {
console.log(`年龄为 ${age} 的用户:`, event.target.result);
};
}
**4. 更新数据**
javascript
function updateUser(db, updatedUser) {
const transaction = db.transaction(['Users'], 'readwrite');
const store = transaction.objectStore('Users');
const request = store.put(updatedUser); // put 会根据主键自动更新或添加
request.onsuccess = () => {
console.log('数据更新成功');
};
}
// 使用示例
updateUser(db, { id: 1, name: 'Alice', age: 31 }); // 更新 ID 为 1 的用户
**5. 删除数据**
javascript
function deleteUser(db, id) {
const transaction = db.transaction(['Users'], 'readwrite');
const store = transaction.objectStore('Users');
const request = store.delete(id);
request.onsuccess = () => {
console.log('数据删除成功');
};
}
**使用 Promise 封装 IndexedDB**
原生 API 使用事件监听比较繁琐,可封装为 Promise:
javascript
class IndexedDB {
constructor(dbName, version, upgradeCallback) {
this.db = null;
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, version);
request.onupgradeneeded = (event) => {
upgradeCallback(event.target.result);
};
request.onsuccess = (event) => {
this.db = event.target.result;
resolve(this);
};
request.onerror = (event) => {
reject(event.target.error);
};
});
}
// 其他方法...
}
// 使用示例
new IndexedDB('MyDatabase', 1, (db) => {
// 创建存储
}).then((db) => {
// 使用 db 实例
});
**注意事项**
1. **兼容性**
主流浏览器(Chrome、Firefox、Safari、Edge)均支持,但 IE 10+ 部分支持。
2. **存储限制**
通常为 50MB 左右(取决于浏览器和设备),超出会触发 `QuotaExceededError`。
3. **事务特性**
事务完成后会自动关闭,无法重复使用。需为每个操作创建新事务。
4. **数据类型**
支持大多数 JavaScript 对象(包括 Date、Array、Blob 等),但不支持函数。
**应用场景**
- 离线应用数据缓存(如 PWA)
- 大量数据的本地存储(如图库、笔记应用)
- 减少网络请求,提升应用性能
IndexedDB 是前端持久化存储的强大工具,但使用复杂度较高。若追求简单,可考虑 `localStorage` 或 `sessionStorage`;若需要更高级的ORM风格API,可尝试第三方库如 **Dexie.js**。