Skip to content

本地存储

元信息

  • 目标:掌握 cookie 之外的纯客户端持久化谱系——KV 阵营(localStorage/sessionStorage)与数据库阵营(IndexedDB/OPFS)的能力边界,能按数据形态选对存储方案
  • 关键概念:localStorage、sessionStorage、IndexedDB、OPFS、对象仓库、事务
  • 关联阶段:cp3
  • 常见误区:以为 localStorage 什么都能存(仅字符串、约 5MB、同步阻塞主线程);以为 IndexedDB 只是放大版 localStorage(它是对象库+索引+事务的异步数据库);以为本地存储的数据会随请求发给服务器(不随 HTTP 走,cookie 才会)

问题的提出

  • cookies 不适合存储大容量数据,因其基于http协议,每次连接均会在客户端和服务器之间被传输,网络压力很大
  • cookies 没有提供结构化的存储接口,完全基于字符串,操作不便

于是浏览器陆续内置了多种纯客户端的本地存储机制。它们分两大阵营:

  • KV(键值对)阵营:localStorage / sessionStorage —— 简单字符串存取,像一个大号字典
  • 数据库阵营:IndexedDB(对象/索引)、OPFS(文件)—— 结构化、可查询、可事务

全家福对照

cookielocalStoragesessionStorageIndexedDBOPFS
出现年代19942009200920102021
存储模型字符串键值字符串键值字符串键值对象库+索引私有文件系统
容量~4KB~5-10MB~5MB数百MB~GB级GB级
随HTTP发送✅ 每次请求
生命周期可设过期永久标签页关闭即清永久永久
API 风格同步同步同步异步(事件)异步(Promise)
事务/索引
典型用途身份/会话凭证偏好设置、草稿一次性表单状态离线应用的主数据库大文件、音视频素材

选型一句话:几 KB 的偏好设置用 localStorage;结构化业务数据、要查询要离线,用 IndexedDB;大文件用 OPFS;需要随请求走的服务端状态,才回到 cookie。

localStorage与sessionStorage

浏览器家族中最早支持的内置本地缓存技术,二者 API 完全相同(getItem/setItem/removeItem/clear),只差生命周期:

  • localStorage: 持久化本地存储。除非主动删除数据,否则数据是永远不会过期的。
  • sessionStorage: 仅存储一个会话(session)中的数据,即只有在同一个会话中的页面,才能访问会话数据。并且当会话结束后数据也随之销毁
import "./styles.css";

document.getElementById("app").innerHTML = `
<h1>Hello world</h1>
`;

KV 存储的局限

  • 安全风险:localStorage 数据以明文形式存储,容易受到 XSS 攻击,攻击者可以通过注入恶意脚本轻松获取存储的敏感信息。
  • 同步阻塞操作:localStorage 的读写操作是同步的,会阻塞主线程,在存储大量数据时可能导致性能问题和界面卡顿。
  • 存储容量有限:大多数浏览器将 localStorage 的存储上限设为 5MB,无法满足现代复杂应用的需求。
  • 只能存储字符串:需要手动序列化和反序列化复杂数据结构,增加了代码复杂度和出错可能。
  • 缺乏高级查询能力:只能按键精确取值,无法按条件查询、排序、建索引——"字典"终究不是"数据库"。

IndexedDB:浏览器里的数据库

容量上限高(通常数百 MB 以上,部分浏览器可达可用磁盘空间的比例),API 全异步。要点:

  • 对象仓库(object store):直接存 JavaScript 对象,无需手动序列化;支持 String、Array、Object、File、Blob、ArrayBuffer、ImageData 等
  • 索引与查询:可对任意字段建索引,用游标(cursor)按范围遍历——这是它与 KV 存储的本质区别
  • 事务机制:读写必须在事务中进行,保证数据完整性
  • 异步 API:基于事件(新版提供 Promise 化接口),不阻塞主线程;可与 Web Workers 配合,把数据处理隔离在主线程之外
  • 遵循同源策略,持久化优先级高于 localStorage
import "./styles.css";

document.getElementById("app").innerHTML = `
<h1>Hello world</h1>
`;

KV 与数据库的分野,是后端世界的老问题在浏览器的重演:Redis 式 KV 胜在简单迅捷,SQLite/MySQL 式数据库胜在结构与查询。前端同样如此——简单偏好用 KV,业务数据用 IndexedDB。 历史注脚:浏览器曾内置过 SQL 风格的 WebSQL(真正的 SQLite),因标准化停滞已废弃,其角色由 IndexedDB 接替;如今要用 SQL 语法操作 IndexedDB,可借助 sql.js(SQLite 编译为 WebAssembly)等方案。

封装工具

原生 IndexedDB API 以事件为基础,写法繁琐,实践中常用封装:

  • localForage — 提供 localStorage 风格的简单 API,底层自动选用 IndexedDB/WebSQL/localStorage,"KV 的易用 + 数据库的容量"
  • idb — IndexedDB 的极薄 Promise 封装
  • Dexie — 流行的 IndexedDB 完整封装,支持链式查询
import "./styles.css";

document.getElementById("app").innerHTML = `
<h1>Hello world</h1>
`;

教程