优先选 IndexedDB;因 localStorage 仅适合小量简单数据(如开关、token),而 IndexedDB 支持大容量、异步操作、索引查询、事务原子性及精准范围筛选,避免主线程阻塞与静默失败。

选 IndexedDB 还是 localStorage,关键看数据是不是“能塞进一张纸条”——如果只是几个开关、一个主题名、一个 token,localStorage 就够用;一旦你要存几百条订单、带时间戳的日志、支持按状态/日期筛选的笔记,localStorage 就会卡住页面、撑爆配额、查得你怀疑人生。
数据量超过 1MB 时,localStorage 会明显拖慢页面
它所有读写都是同步的,主线程必须等整个字符串 parse 完或 stringify 完才能继续。实测存 2MB JSON 到 localStorage,getItem() 可能卡主线程 400ms 以上;而同样数据在 IndexedDB 中用事务分片读取,耗时通常压在 20–60ms,且 UI 完全不卡。
- localStorage 写入超限不会报错,而是静默失败或抛
QuotaExceededError,很难及时发现 - IndexedDB 虽然要写
onupgradeneeded和transaction,但容量上限高(Chrome 可达磁盘空间的 50%),且会主动触发storagequotaexceeded事件 - 别信“先用 localStorage,以后再迁”——数据结构一复杂,迁移成本远高于初期多写十几行
IndexedDB初始化代码
需要按字段查、范围查、条件删,必须用 IndexedDB
比如查“过去 7 天创建的未完成任务”,localStorage 得把全部数据 JSON.parse() 出来,再用 filter() 遍历;IndexedDB 只需建个 createdTime 索引,配合 IDBKeyRange.bound() 一次精准拉取。
- localStorage 不支持索引、游标、范围查询,所谓“搜索”全是内存暴力遍历
- IndexedDB 的
objectStore.delete()支持传IDBKeyRange批量删,而 localStorage 只能逐个removeItem() - 没在
onupgradeneeded里建好索引?查询就退化成全表扫描,性能反而不如 localStorage
要保证多步操作原子性,只有 IndexedDB 提供事务
比如本地记一笔“扣款 + 更新余额 + 记录流水”,这三步要么全成功,要么全回滚。localStorage 没事务机制,出错只能靠人工补救;IndexedDB 的 transaction 天然支持 ACID,abort() 一下就干净回退。
立即学习“前端免费学习笔记(深入)”;
- localStorage 写入中途报错(如磁盘满),已写入的键不会自动清理,状态不一致风险高
- IndexedDB 事务中任意操作失败,整个事务自动 abort,无需手动清理中间状态
- 注意:别在一个事务里塞几千条写入——建议单事务 ≤ 500 条,否则锁表太久,反而影响并发
真正容易被忽略的不是 API 多难,而是数据增长后行为的不可控性:localStorage 在 10KB 时很轻快,到 5MB 时已经让页面间歇性卡顿,但这种劣化是渐进的、难以监控的;IndexedDB 初期要处理版本、索引、错误重试,但一旦搭好,后续加字段、扩数据、改查询逻辑,几乎不用动底层存储结构。



















