localstorage 和 indexeddb 是分工协作的搭档:前者负责轻量、高频键值数据(如登录态、配置项),后者承担结构化、大容量、需查询的业务数据(如商品目录、消息历史),二者分层清晰、边界明确,协同构建健壮离线应用。

localStorage 和 IndexedDB 不是“二选一”的替代关系,而是分工明确的协作搭档。真正健壮的离线 Web 应用,往往同时用上两者——各干各的活,不越界、不冗余、不拖慢。
localStorage 负责轻量、高频、键值型数据
它适合存那些结构简单、读写频繁、无需查询逻辑的小数据:
- 用户登录态(如 token、refreshToken),配合 Tauri 安全 API 或加密后写入,重启后快速恢复会话
- UI 配置项(主题色、语言偏好、折叠状态),直接映射到组件响应式状态,毫秒级读取
- 表单草稿或临时编辑缓存(如 textarea 内容),配合 useEffect 实时同步,避免意外刷新丢失
- 跨标签页状态广播信号(如 doc_sync_status),仅作轻量通知,不承载业务数据
IndexedDB 承担结构化、大容量、需查询的数据
它是真正的客户端数据库层,用来存业务核心数据:
- 商品目录(5000+ SKU)、聊天消息历史、笔记内容等结构复杂、体积较大的数据
- 需要按时间范围、分类、状态等多条件筛选的场景(如“最近7天未读消息”)
- 支持事务的原子操作,比如“添加消息 + 更新会话最后时间 + 增加未读数”必须整体成功或失败
- 离线期间的编辑动作日志(insert/update/delete 记录),带 timestamp 和 clientId,为后台同步提供依据
协同的关键:分层清晰、边界明确
二者混用但绝不交叉,典型分层策略如下:
- 读取路径优化:高频访问字段(如用户昵称、头像 URL)先查 localStorage;完整用户资料从 IndexedDB 加载后,再拆出高频字段同步进 localStorage
- 写入职责分离:配置变更直接写 localStorage;新增一条订单记录则走 IndexedDB 事务,完成后可触发 localStorage 状态更新(如 order_count)用于 UI 快速反馈
- 失效联动机制:当 IndexedDB 中某类数据批量更新(如商品目录刷新),主动清除对应 localStorage 缓存键,避免 stale data
- 错误降级兜底:IndexedDB 初始化失败(如用户禁用)时,退化为 localStorage 存简化数据,保证基础功能可用
避坑提醒:别让 localStorage 变成“假数据库”
常见误用会拖垮体验:
- 把整个用户对象 JSON.stringify 后塞进 localStorage —— 数据一过百条就卡顿,且无法按字段查
- 用 localStorage 模拟索引(如拼接 key:user_123_name、user_123_email)—— 维护成本高,删除/更新极难原子化
- 监听 storage 事件做主同步逻辑 —— 该事件不触发当前页,也无法保证顺序,只适合 UI 广播










