Appearance
IndexedDB 本地结构化存储
IndexedDB 是浏览器内置的非关系型数据库,专为客户端存储大量结构化数据设计。
参考:
对比其它本地存储方式
| 存储方式 | 生命周期 | 存储容量 | 与服务器交互 | 数据类型 | 主要应用场景 |
|---|---|---|---|---|---|
| cookie | 可设置过期时间 | 4KB | 每次HTTP请求自动携带 | 字符串 | 身份验证、会话管理 |
| sessionStorage | 会话结束时清除 | 5MB | 仅在客户端存储 | 字符串 | 页面间临时数据传递 |
| localStorage | 永久存储,除非主动删除 | 5MB | 仅在客户端存储 | 字符串 | 用户偏好设置、主题配置 |
| IndexedDB | 永久存储,除非主动删除 | 理论上无上限 | 仅在客户端存储 | 结构化数据 | 大量结构化数据、离线应用 |
兼容
浏览器支持情况良好。
- Chrome 25+
- Firefox 16+
- Safari 6.1+
- Edge 12+
- iOS Safari 6.1+
- Android Browser 4.4+
js
if ("indexedDB" in window) {
// 支持IndexedDB
}核心概念
1. 数据库(Database)
- 每个源(域名)可创建多个数据库,但通常一个应用使用一个数据库。
- 数据库通过名称和版本号唯一标识,版本升级需显式处理。
2. 对象存储(Object Store)
- 类似数据库的“表”,存储键值对数据。
- 每个对象存储需定义主键(keyPath),支持自动生成主键(autoIncrement)。
- 可创建多个索引(Index),用于快速查询非主键字段。
3. 事务(Transaction)
- 所有数据操作必须在事务中完成,确保原子性。
- 事务模式:
- readonly:只读,性能最佳。
- readwrite:读写,可能触发版本升级。
- versionchange:数据库结构变更(如创建/删除对象存储)。
4. 游标(Cursor)
- 用于遍历对象存储或索引中的数据,支持范围查询和条件过滤。
操作流程
1. 打开/创建数据库
js
const request = indexedDB.open('myDatabase', 1); // 名称 + 版本(每次结构变更如新增对象存储,需升级版本)
request.onerror = (event) => {
console.error('数据库打开失败:', event.target.error);
};
request.onsuccess = (event) => {
const db = event.target.result; // 获取数据库实例
console.log('数据库已打开:', db.name);
};2. 添加数据
js
const transaction = db.transaction('users', 'readwrite'); // 开启读写事务
const store = transaction.objectStore('users'); // 获取对象存储实例
const request = store.add({ name: 'Alice', email: 'test@qq.com' }); // 添加数据
request.onsuccess = () => console.log('数据添加成功');
request.onerror = (e) => console.error('添加失败:', e.target.error);3. 读取数据
js
const transaction = db.transaction('users', 'readonly'); // 开启只读事务
const store = transaction.objectStore('users'); // 获取对象存储实例
store.keyPath = 'email'; // 设置主键字段为 email
const request = store.get('test@qq.com'); // 根据主键读取数据
request.onsuccess = (event) => {
const user = event.target.result;
if (user) {
console.log('读取到用户:', user);
} else {
console.log('未找到用户');
}
};
request.onerror = (e) => console.error('读取失败:', e.target.error);4. 更新数据
js
const transaction = db.transaction('users', 'readwrite'); // 开启读写事务
const store = transaction.objectStore('users'); // 获取对象存储实例
store.keyPath = 'email'; // 设置主键字段为 email
const request = store.put({ name: 'Alice Updated', email: 'test@qq.com' }); // 更新数据
request.onsuccess = () => console.log('数据更新成功');
request.onerror = (e) => console.error('更新失败:', e.target.error);5. 删除数据
js
const transaction = db.transaction('users', 'readwrite'); // 开启读写事务
const store = transaction.objectStore('users'); // 获取对象存储实例
store.keyPath = 'email'; // 设置主键字段为 email
const request = store.delete('test@qq.com'); // 按主键删除
request.onsuccess = () => console.log('数据删除成功');
request.onerror = (e) => console.error('删除失败:', e.target.error);6. 遍历数据
js
const transaction = db.transaction('users', 'readonly'); // 开启只读事务
const store = transaction.objectStore('users'); // 获取对象存储实例
store.keyPath = 'email'; // 设置主键字段为 email
const request = store.openCursor(); // 打开游标
request.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
console.log('遍历到用户:', cursor.value);
cursor.continue(); // 继续遍历下一条数据
} else {
console.log('遍历完成');
}
};
request.onerror = (e) => console.error('遍历失败:', e.target.error);7. 关闭数据库
js
db.close(); // 关闭数据库连接IndexedDB 的简化库 localForage
大多数场景使用不到 IndexedDB,因为它的 API 相对复杂,且性能不如 localStorage。
有些需要IndexedDB场景, 大概会顺手用localStorage 写个查询算法解决。
把indexedDB简单封装成"localStorage" 就是 localForage
- localForage是一个JavaScript库,能够类似localStorage的存储。
- 他是异步存储,可以优化你的web应用程序的离线体验,而且能存储多种类型的数据。
- localForage有一个优雅的降级策略,如果浏览器不支持indexedDB或者WebSQL则使用localStorage。
不支持复杂查询,只能通过遍历所有数据来实现。
1. 安装
bash
npm install localforage2. 引入
js
import localForage from 'localforage';3. 存储
js
// 1:存普通数据
localforage.setItem('somekey', 'some value').then(function (value) {
// 当值被存储后,可执行其他操作
console.log(value);
}).catch(function(err) {
// 当出错时,此处代码运行
console.log(err);
});
// 2:存一个数组
localforage.setItem('myarray', [1, 2, 'three']).then(function(value) {
// 如下输出 `1`
console.log(value[0]);
}).catch(function(err) {
// 当出错时,此处代码运行
console.log(err);
});4. 读取
js
// 1:读取普通数据
localforage.getItem('somekey').then(function(value) {
// 如下输出 `some value`
console.log(value);
}).catch(function(err) {
// 当出错时,此处代码运行
console.log(err);
});
// 2:读取数组
localforage.getItem('myarray').then(function(value) {
// 如下输出 `1`
console.log(value[0]);
}).catch(function(err) {
// 当出错时,此处代码运行
console.log(err);
});其它库
Dexie.js
- 功能丰富,支持索引、事务、批量操作等
- 复杂数据管理、多表结构的应用
idb
- 接近原生 IndexedDB API 的轻量封装
- 对性能要求高,熟悉 IndexedDB 的项目