在前端开发中,我们会遇到这样的问题:
- 需要在浏览器中存储大量结构化数据
- localStorage 空间太小,性能太差
- 需要支持索引,事务,复杂查询
- 希望数据能离线可用
这时候,indexedDB 就是最合适的选择
本文将带你系统了解:
- indexedDB 是什么
- 它能解决什么问题
- 核心概念与基本用法
- 实际使用中的注意事项
一 。 indexedDB 是什么
indexedDB 是浏览器内置的一种低层级NoSQL 数据库
它具有以下特点
- 存储在浏览器本地
- 支持大量数据(通常是MB - GB级)
- 支持索引(index)
- 支持事务(Transaction)
- 异步API,不阻塞主线程
一句话总结:
indexedDB = 浏览器里的本地数据库
二. 为什么不用localStorage?
| 特性 | localStorage | IndexedDB |
|---|---|---|
| 存储容量 | ~5MB | 几十 MB 甚至 GB |
| 数据类型 | 字符串 | 任意 JS 对象 |
| 是否异步 | ❌ 同步 | ✅ 异步 |
| 索引 | ❌ | ✅ |
| 事务 | ❌ | ✅ |
| 查询能力 | ❌ | ✅ |
结论:
localStorage适合少量简单数据
indexedDB适合复杂,长期,本地数据存储
三. indexedDB 的核心概念
indexedDB 的概念和数据库很像,但名字略有不同
1. 数据库
一个站点(域名)可以创建多个数据库
const request=indexedDB.open('myOB',1);
- 第一个参数: 数据库名
- 第二个参数: 版本号(升级用)
2. 对象仓库(Object Store)
可以理解为 表(Table)
db.createObjectStore('users', {
keyPath: 'id'
});
keyPath: 主键字段
每个Object store 存储一类数据
3. 索引(Index)
indexedDB中的index就是索引,用于加速查询
store.createIndex('emailIndex', 'email', { unique: true });
- 一个Object store 可以有多个index
- 查询时可以直接走索引
4. 事务
所有读写操作必须在事务中完成
const tx = db.transaction('users', 'readwrite');
const store = tx.objectStore('users');
事务具有:
- 原子性
- 自动提交/回滚
四. 基本使用示例
- 打开数据库并创建表
const request = indexedDB.open('myDB', 1);
request.onupgradeneeded = event => {
const db = event.target.result;
const store = db.createObjectStore('users', {
keyPath: 'id'
});
store.createIndex('nameIndex', 'name');
};
request.onsuccess = event => {
const db = event.target.result;
console.log('数据库打开成功');
};
- 插入数据
const tx = db.transaction('users', 'readwrite');
const store = tx.objectStore('users');
store.add({
id: 1,
name: 'Tom',
age: 20
})
- 通过主键查询
store.get(1).onsuccess = e => {
console.log(e.target.result);
};
- 通过索引查询
const index = store.index('nameIndex');
index.get('Tom').onsuccess = e => {
console.log(e.target.result);
};
五.indexedDB 适合哪些场景?
非常适合
- 离线应用(PWA)
- 本地缓存接口数据
- 前端日志 / 埋点缓存
- 大文件分片存储
- IM / 邮箱 / 草稿箱
不适合
- 跨浏览器共享数据
- 需要服务端强一致的数据
- 简单key-value 少量存储(localStorage更简单)
六. 使用indexedDB 的常见坑
API 过于底层,回调繁琐
indexedDB 原生API 非常啰嗦,实际开发中一般会用封装库:
- idb (推荐)
import { openDB } from 'idb';
const db = await openDB('myDB', 1, {
upgrade(db) {
db.createObjectStore('users', { keyPath: 'id' });
}
});
七. indexedDB vs Web Storage 总结
一句话总结:
indexedDB 是前端领域真正意义上的"本地数据库"
当你遇到以下需求时,请直接考虑它:
- 数据量大
- 结构复杂
- 需要索引和事务
- 需要离线能力