Django或Spring等服务器端框架主要使用会话(Session)管理来处理服务器端的状态,并通过Cookie来识别客户端。服务器管理状态是很方便的。
但在React、Vue、Angular等SPA(Single Page Application)环境中,客户端(浏览器)承担了很多角色。与服务器的通信主要通过API交换数据,而用户的状态或UI设置通常在客户端直接管理。
此时,需要决定数据存储在“哪里”,浏览器为此提供了几种存储方式。明确了解每种存储的特点和用途是高效的SPA开发的关键。
今天我们将了解浏览器的主要存储:Cookie、Local Storage、Session Storage以及IndexedDB。
1. Cookie
Cookie是浏览器存储的元老。最初是为了在客户端和服务器之间保持状态(Stateful)而设计的。
-
特点:
-
小容量: 限制约4KB,容量非常小。
-
服务器传送: 最大的特点。Cookie会自动包含在所有HTTP请求中,并传送到服务器。这在服务器想要了解客户端状态时很有用,但也可能因为不必要的数据传输而降低性能。
-
过期时间: 可以通过
Expires或Max-Age属性设置到期日期和时间。如果不设置,则作用为会话Cookie(浏览器关闭时删除)。 -
安全选项: 可以设置
HttpOnly(防止JavaScript访问)、Secure(只在HTTPS下传输)等安全设置。
-
-
主要用途:
-
认证 (Authentication): 存储服务器发出的登录认证令牌(JWT等),使得服务器可以在用户每次页面跳转时识别用户。(尤其是与
HttpOnly选项一起使用) -
用户追踪及广告: 用于追踪用户的访问记录或行为模式。(例如:Google Analytics)
-
“今天不再显示”弹窗
-
2. Local Storage
这是HTML5推出的Web Storage API的一部分。为了弥补Cookie的缺点(容量小、自动服务器传送)而出现。
-
特点:
-
大容量: 每个浏览器不同,但通常提供5MB〜10MB的充足容量。
-
不传送给服务器: Local Storage将数据仅保存在客户端,不会自动发送给服务器。适合存储服务器不需要了解的数据。
-
持久性: 数据永久保留。除非用户手动删除浏览器缓存或通过JavaScript代码调用
localStorage.removeItem(),否则数据不会消失。 -
简便的API: 提供
localStorage.setItem('key', 'value')、localStorage.getItem('key')等易于使用的API。(只能存储字符串)
-
-
主要用途:
-
用户设置存储: 存储用户选择的UI设置,如深色模式/浅色模式设置、语言设置等。
-
非敏感数据存储: 用户最近查看的内容列表、自动保存功能等。
-
数据缓存: 缓存API响应中不常变更的数据,以减少不必要的请求。
-
3. Session Storage
与Local Storage几乎共享所有特点,但在数据的生命周期(Life Cycle)上有决定性差异。
-
特点:
-
大容量: 与Local Storage相同,约提供5MB的容量。
-
不传送给服务器: 仅存储在客户端。
-
基于会话的生命周期: 数据仅限于当前浏览器标签页(或窗口)。关闭标签后,Session Storage中的所有数据将立刻删除。
-
数据隔离: 同一域名下不同标签间不共享数据。
-
-
主要用途:
-
一次性数据存储: 仅在当前标签中有效的信息。
-
临时表单数据: 分多个步骤的会员注册表单或问卷填写时,用户在关闭标签前输入的内容临时存储。
-
刷新时数据保留: 页面刷新时保持数据,但关闭标签后数据消失的场景。
-
4. IndexedDB
如果说Local Storage和Session Storage是简单的Key-Value存储,IndexedDB就是浏览器内存在真正的事务数据库系统。
-
特点:
-
大容量存储: 可以存储从数百MB到数GB的数据,具体取决于用户的磁盘空间(根据浏览器政策而异)。
-
多种数据类型: 可以存储的不仅是字符串,还包括JavaScript对象、文件(Blob)、数组等复杂结构的数据。
-
支持交易(Transaction): 确保数据的完整性和一致性。可以将多个操作作为一个单元进行处理。
-
异步(Asynchronous) API: IndexedDB的所有操作都是异步处理的。这意味着在读取和写入大数据时也不会阻塞主UI线程,从而保持应用程序响应性。
-
支持索引(Index): 可以创建索引以便根据特定字段快速搜索数据。
-
-
缺点:
- 复杂的API: 相比
localStorage,API复杂且难以使用。(因此经常和Dexie.js、idb等包装器(Wrapper)库一起使用。)
- 复杂的API: 相比
-
主要用途:
-
离线Web应用程序(PWA): 存储需要在离线状态下工作的重要数据。(例如:离线文档编辑器)
-
大规模应用状态缓存: Gemini或ChatGPT将在浏览器中存储以前的对话记录,或在管理复杂用户数据时使用。
-
用户生成内容的临时存储: 在用户撰写长文本或编辑图像数据时安全保存到服务器上传之前。
-
5. 一目了然的比较

四种存储的特点汇总如下表:
| 标准 | Cookie | Local Storage | Session Storage | IndexedDB |
|---|---|---|---|---|
| 容量 | ~ 4KB | ~ 5-10MB | ~ 5MB | ~ GB+ (大容量) |
| 过期时间 | 手动设置 | 永久性 | 关闭标签时 | 永久性 |
| 服务器传送 | O (自动传送) | X (客户端专用) | X (客户端专用) | X (客户端专用) |
| 访问范围 | 同一域名 | 同源 | 当前标签 | 同源 |
| 数据形式 | 字符串 | 字符串 | 字符串 | 对象、文件、Blob等 |
| API | 同步 (复杂) | 同步 (简便) | 同步 (简便) | 异步 (复杂) |
| 搜索功能 | X | X | X | O (使用索引) |
6. 结论: 何时使用什么?
在开发如React的SPA时,明确区分这四种存储的用途是很重要的。
-
Cookie:
-
用于服务器必须知道的数据。(例如:安全性重要的认证令牌)
-
使用
HttpOnly选项来保护令牌免受XSS攻击是个好主意。
-
-
Local Storage:
-
用于需要在用户重启浏览器后仍需保留的简单数据。
-
(例如:用户UI主题设置、语言选择)
-
-
Session Storage:
-
用于仅当前操作(标签)中需要的临时数据。
-
(例如:多步骤表单填写中的临时保存)
-
-
IndexedDB:
-
在需要结构化大数据或离线支持时使用。
-
(例如:复杂的应用状态、对话记录缓存、离线文档数据)
-
重要安全提示: Local Storage、Session Storage和IndexedDB可以被JavaScript轻松访问。这意味着它们易受XSS(跨站脚本攻击)的威胁。切不可在此存储密码、个人识别信息、敏感认证令牌等。(认证令牌最好使用
HttpOnlyCookie来存储,这样更安全。)
目前沒有評論。