Javascript IndexedDB 数据库
IndexedDB
是一个浏览器提供的低级API,用于在客户端存储大量的结构化数据。它比 localStorage
和 sessionStorage
更加强大,可以存储更复杂的数据类型(如对象、数组等),并且支持异步操作。它允许你以键值对的形式存储数据,并提供查询和索引功能来高效地检索数据。
以下是关于 IndexedDB
的一些基本概念和操作示例。
1. IndexedDB
基本概念
- 数据库 (Database):
IndexedDB
中的顶层对象。每个数据库包含多个对象存储区(Object Store)。 - 对象存储区 (Object Store):类似于传统数据库中的表,用于存储数据。每个对象存储区都有一个键(Key),可以通过键来快速访问数据。
- 事务 (Transaction):所有对
IndexedDB
的读写操作都必须在事务中进行。 - 游标 (Cursor):用于迭代数据,尤其是当你需要遍历整个对象存储区时。
2. 创建和使用 IndexedDB
以下是创建数据库、对象存储区以及执行基本的 IndexedDB
操作(如写入和读取)的示例。
示例:使用 IndexedDB
存储和读取数据
// 打开数据库,若不存在会创建
const request = indexedDB.open('MyDatabase', 1);
// 数据库升级(版本号变更时调用)
request.onupgradeneeded = function(event) {
const db = event.target.result;
// 创建对象存储区(类似于表)
const store = db.createObjectStore('users', { keyPath: 'id' });
// 创建索引(根据名字查询)
store.createIndex('name', 'name', { unique: false });
};
// 打开数据库成功后执行
request.onsuccess = function(event) {
const db = event.target.result;
console.log('Database opened successfully.');
// 向对象存储区插入数据
const transaction = db.transaction('users', 'readwrite');
const store = transaction.objectStore('users');
const user = { id: 1, name: 'John Doe', age: 30 };
store.add(user);
transaction.oncomplete = function() {
console.log('Data saved successfully.');
};
transaction.onerror = function() {
console.log('Error saving data.');
};
};
// 错误处理
request.onerror = function(event) {
console.error('Database error:', event.target.errorCode);
};
3. 读取数据
读取数据时,你可以通过键值(key)获取数据,或者使用游标进行遍历。
通过 get
方法读取数据
const request = indexedDB.open('MyDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction('users', 'readonly');
const store = transaction.objectStore('users');
const getRequest = store.get(1); // 获取 ID 为 1 的用户
getRequest.onsuccess = function() {
const user = getRequest.result;
console.log('User data:', user);
};
getRequest.onerror = function() {
console.log('Error retrieving data.');
};
};
使用游标(Cursor)遍历数据
const request = indexedDB.open('MyDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction('users', 'readonly');
const store = transaction.objectStore('users');
const cursorRequest = store.openCursor();
cursorRequest.onsuccess = function(event) {
const cursor = event.target.result;
if (cursor) {
console.log('User:', cursor.value);
cursor.continue(); // 继续迭代
} else {
console.log('No more data.');
}
};
cursorRequest.onerror = function() {
console.log('Error iterating data.');
};
};
4. 更新和删除数据
更新数据
const request = indexedDB.open('MyDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction('users', 'readwrite');
const store = transaction.objectStore('users');
const updatedUser = { id: 1, name: 'John Smith', age: 35 };
store.put(updatedUser); // 使用 put 方法可以更新已有数据
transaction.oncomplete = function() {
console.log('Data updated successfully.');
};
transaction.onerror = function() {
console.log('Error updating data.');
};
};
删除数据
const request = indexedDB.open('MyDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction('users', 'readwrite');
const store = transaction.objectStore('users');
store.delete(1); // 删除 ID 为 1 的用户
transaction.oncomplete = function() {
console.log('Data deleted successfully.');
};
transaction.onerror = function() {
console.log('Error deleting data.');
};
};
5. 版本管理
如果你修改了数据库的结构(例如添加新的对象存储区或索引),需要更新版本号并在 onupgradeneeded
事件中进行相应的处理。
const request = indexedDB.open('MyDatabase', 2); // 新版本号 2
request.onupgradeneeded = function(event) {
const db = event.target.result;
// 检查对象存储区是否存在,若不存在则创建
if (!db.objectStoreNames.contains('users')) {
const store = db.createObjectStore('users', { keyPath: 'id' });
}
// 添加新的索引
const store = db.transaction.objectStore('users');
store.createIndex('email', 'email', { unique: true });
};
6. 异常和错误处理
在进行 IndexedDB
操作时,务必进行错误处理,捕获可能发生的异常。
const request = indexedDB.open('MyDatabase', 1);
request.onerror = function(event) {
console.error('Database error:', event.target.error);
};
7. 清理和删除数据库
如果你需要删除数据库,可以使用 indexedDB.deleteDatabase()
方法:
const request = indexedDB.deleteDatabase('MyDatabase');
request.onsuccess = function() {
console.log('Database deleted successfully.');
};
request.onerror = function() {
console.error('Error deleting database.');
};
8. IndexedDB
与 localStorage
比较
特性 | IndexedDB | localStorage |
---|---|---|
数据存储方式 | 支持键值对和索引,可以存储对象、数组等复杂数据 | 只能存储字符串 |
存储容量 | 可存储更大数据(每个浏览器大约 5MB-50MB) | 通常每个域名限制 5MB |
异步操作 | 支持异步操作 | 不支持异步操作 |
查询能力 | 支持索引和游标,支持更复杂的查询 | 无查询能力,只能通过键获取数据 |
支持的数据类型 | 支持存储 JavaScript 对象、数组等 | 只能存储字符串,需要手动序列化和反序列化 |
使用复杂度 | 相对较复杂,需要更多的配置和操作 | 非常简单,直接使用 setItem 和 getItem |
总结
IndexedDB
是一个强大的客户端存储解决方案,适合存储大量结构化数据,支持异步操作和查询。它比 localStorage
更加灵活和高效,但相对而言也更为复杂。适用于需要存储大量数据或进行复杂查询的场景。如果你的应用需要存储超过几MB的数据或者需要更复杂的存储方案,IndexedDB
是一个非常好的选择。