IndexedDB 是什么?它适用于什么场景?
IndexedDB 是浏览器提供的一种底层 API,用于在客户端(用户的浏览器)存储大量的结构化数据(包括文件/二进制大对象 Blobs)。
简单来说,你可以把它理解为浏览器内置的一个非关系型数据库(NoSQL Database)。
以下是关于它的详细介绍和适用场景:
一、 IndexedDB 是什么?(核心特性)
与 LocalStorage 或 Cookie 不同,IndexedDB 功能更强大,主要特点如下:
- 存储容量大:
- LocalStorage 通常限制在 5MB - 10MB。
- IndexedDB 的容量通常取决于用户磁盘剩余空间(通常可以达到几百 MB 甚至 GB 级别)。
- 键值对存储(Key-Value):
- 它是一个对象仓库(Object Store)。
- 不同于 LocalStorage 只能存字符串,IndexedDB 可以直接存储 JavaScript 对象、数组,甚至 二进制数据(ArrayBuffer, Blob, File)。
- 异步操作(Asynchronous):
- IndexedDB 的操作(读写)不会阻塞浏览器的主线程。这意味着在读写大量数据时,页面不会“卡顿”。
- 相比之下,LocalStorage 是同步的,数据量大时会阻塞页面渲染。
- 支持事务(Transactional):
- 这意味着一系列操作要么全部成功,要么全部失败(回滚),保证了数据的一致性。
- 支持索引(Indexing):
- 你可以给存储的对象属性建立索引,从而实现高性能的搜索和查询。
- 同源策略:
- 和 Cookie、LocalStorage 一样,IndexedDB 受同源策略限制,网页只能访问自身域名下的数据库。
二、 IndexedDB 适用于什么场景?
由于其大容量和异步特性,IndexedDB 非常适合以下场景:
1. 离线应用(Offline First / PWA)
这是 IndexedDB 最核心的用途。
- 场景:用户在没有网络(如在地铁、飞机上)时,依然可以使用网页应用。
- 做法:将 API 返回的数据、文章内容、图片等缓存在 IndexedDB 中。当网络断开时,从 IndexedDB 读取数据展示;当网络恢复时,再与服务器同步。
2. 存储大量结构化数据
- 场景:电商网站的商品目录、复杂的 CMS 系统、管理后台的大量表格数据。
- 做法:如果数据量超过 5MB,或者数据结构复杂(嵌套对象),LocalStorage 无法胜任,必须使用 IndexedDB。
3. 存储文件和二进制数据
- 场景:在线图片编辑器、音频/视频处理应用、网盘类应用。
- 做法:用户上传的图片、生成的 PDF、录制的音频可以直接以
Blob或File对象的形式存入 IndexedDB,无需转换成 Base64 字符串(Base64 会增加体积且处理慢)。
4. 客户端缓存(提升性能)
- 场景:数据分析大屏、地图应用。
- 做法:有些静态资源或很少变动的 API 数据(如城市列表、字典表),每次都从服务器拉取很浪费带宽。可以将其持久化存储在 IndexedDB 中,极大提升二次加载速度。
5. 复杂的应用状态管理
- 场景:类似 Figma、Notion 这样复杂的 Web 应用。
- 做法:用户的每一步操作历史(用于撤销/重做)、草稿内容都需要实时保存。IndexedDB 的事务和异步特性可以保证在频繁自动保存时不仅数据安全,还不会卡顿界面。
三、 IndexedDB 与 LocalStorage 的简单对比
| 特性 | LocalStorage | IndexedDB |
|---|---|---|
| 容量 | 小 (约 5MB) | 大 (> 250MB,视磁盘而定) |
| 数据类型 | 仅字符串 (String) | JS对象、文件、二进制、数组等 |
| 操作方式 | 同步 (阻塞主线程) | 异步 (不阻塞) |
| 查询能力 | 只能按 Key 取值 | 支持索引,可按属性查询 |
| 上手难度 | 极简 | 较复杂 (原生 API 繁琐) |
四、 开发建议
虽然 IndexedDB 很强大,但它的原生 API 设计得比较古老且繁琐(基于事件监听,容易写出回调地狱)。
在实际开发中,强烈建议使用封装库,它们提供了更现代的 Promise/Async-Await 语法:
- Dexie.js (最推荐):功能强大,语法优雅,支持 TypeScript,社区活跃。
- localForage:API 极其简单(类似 LocalStorage 的 getItem/setItem),底层自动降级(如果不支持 IndexedDB 则回退到 WebSQL 或 LocalStorage)。
- idb:一个轻量级的库,主要将 IndexedDB 包装成 Promise 形式。
总结:
如果你只需要存个 Token 或简单的用户配置,用 LocalStorage。
如果你需要开发离线应用、存图片/文件、或者缓存大量数据,IndexedDB 是唯一的选择。