同学们好,我是 Eugene(尤金),一个拥有多年中后台开发经验的前端工程师~
(Eugene 发音很简单,/juːˈdʒiːn/,大家怎么顺口怎么叫就好)
你是否也有过:明明学过很多技术,一到关键时候却讲不出来、甚至写不出来?
你是否也曾怀疑自己,是不是太笨了,明明感觉会,却总差一口气?
就算想沉下心从头梳理,可工作那么忙,回家还要陪伴家人。
一天只有24小时,时间永远不够用,常常感到力不从心。
技术行业,本就是逆水行舟,不进则退。
如果你也有同样的困扰,别慌。
从现在开始,跟着我一起心态归零,利用碎片时间,来一次彻彻底底的基础扫盲。
这一次,我们一起慢慢来,扎扎实实变强。
不搞花里胡哨的理论堆砌,只分享看得懂、用得上的前端干货,
咱们一起稳步积累,真正摆脱“面向搜索引擎写代码”的尴尬。
一、开篇:为什么要关心浏览器存储?
日常开发里经常会遇到:
- Token 存哪:登录后 token 放在哪、刷新页面怎么不丢?
- 用户配置:主题、语言、侧边栏收起状态,下次打开要记住。
- 列表筛选:表格的筛选条件、分页、排序,希望刷新后还能保留。
这些都要用到浏览器存储。但 localStorage、sessionStorage、cookie 该怎么选?场景对应错了,就会有跨 tab 不同步、隐私泄露、存不下等问题。
下面从概念 → 用法 → 实战场景 → 选型 → 踩坑,把三者讲清楚:日常该用哪个、为什么这么用、容易踩哪些坑。
二、概念扫盲
先用一张表看清三者区别:
| 特性 | localStorage | sessionStorage | cookie |
|---|---|---|---|
| 生命周期 | 持久化,除非手动删除 | 关闭标签页即失效 | 可设置过期时间 |
| 容量 | 约 5MB | 约 5MB | 约 4KB |
| 作用域 | 同源下所有页面共享 | 仅当前标签页 | 同源共享,可设置 path |
| 是否随请求发送 | 否 | 否 | 是(每次请求自动带) |
| API 风格 | getItem / setItem | 同上 | document.cookie 字符串操作 |
一句话记:
- localStorage:长期存、全页面共享,适合偏好、配置。
- sessionStorage:仅当前标签页、关掉就丢,适合临时状态。
- cookie:每次请求都会带上,适合需和服务端交互的(如认证、会话)。
三、localStorage:持久化存储
3.1 是什么?
localStorage 是持久化存储,数据不会过期,除非主动删除,或用户清除浏览器数据。同源下所有页面共享。
3.2 基本用法
// 存
localStorage.setItem('theme', 'dark');
// 取
const theme = localStorage.getItem('theme'); // 'dark'
// 删
localStorage.removeItem('theme');
// 清空所有
localStorage.clear();
注意:只能存字符串。对象需要序列化:
// 存对象
const userConfig = { theme: 'dark', lang: 'zh' };
localStorage.setItem('userConfig', JSON.stringify(userConfig));
// 取对象
const config = JSON.parse(localStorage.getItem('userConfig') || '{}');
3.3 适用场景
- 用户主题、语言、侧边栏状态
- 需要持久化的列表筛选、排序、分页
- 表单草稿(不敏感数据)
- Token(前提是放在合理的安全体系里)
四、sessionStorage:会话级存储
4.1 是什么?
sessionStorage 的生命周期只到当前标签页关闭。新开标签页是新会话,数据不共享。
4.2 基本用法
// 用法和 localStorage 一样
sessionStorage.setItem('tempId', 'abc123');
const tempId = sessionStorage.getItem('tempId');
sessionStorage.removeItem('tempId');
4.3 适用场景
- 当前页的临时数据(如多步表单的中间页)
- 不希望跨 tab 共享的数据
- 表单防重复提交用的临时标记
- 一些只对当前会话有用的临时 token
4.4 常见误区
很多人以为 sessionStorage 和“会话”一样,关浏览器才清空。实际上:
- 关闭标签页 → 数据就没了
- 刷新页面 → 数据还在
- 新开标签页 → 新会话,看不到旧数据
五、cookie:会被请求携带的存储
5.1 是什么?
cookie 是早期方案,容量小,每次 HTTP 请求会自动带上(同域且 path 匹配时)。因此常用来存 sessionId、token 等需要和服务端交互的信息。
5.2 基本用法
cookie 需要手动拼字符串,原生 API 不友好:
// 设置 cookie(需手动拼接)
document.cookie = 'token=abc123; path=/; max-age=3600'; // 1小时过期
// 读取 cookie
const cookies = document.cookie; // "token=abc123; theme=dark"
// 需要自己解析
function getCookie(name) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
return match ? match[2] : null;
}
getCookie('token'); // 'abc123'
常用属性说明:
| 属性 | 含义 |
|---|---|
path=/ | 哪些路径会携带此 cookie |
max-age=3600 | 多少秒后过期 |
domain=.example.com | 子域名共享 |
Secure | 仅 HTTPS 传输 |
HttpOnly | 禁止 JS 访问,防 XSS 读 token |
5.3 适用场景
- 登录凭证(sessionId、token),尤其是需要服务端校验时
- 与后端交互的会话状态
- 老项目或接口强依赖 cookie 的场景
现代项目里,很多 token 用 localStorage 存,请求时通过 Authorization 头发送,而不再用 cookie。这取决于你的前后端约定和安全方案。
六、实战场景:该用哪个?
6.1 Token 存储
常见做法有三种:
| 方式 | 优点 | 缺点 |
|---|---|---|
| localStorage | 刷新不丢、跨 tab 共享、实现简单 | 易受 XSS 攻击读走 token |
| sessionStorage | 关 tab 即失效,相对更安全 | 刷新会丢,需配合刷新 token 逻辑 |
| cookie (HttpOnly) | JS 无法读取,防 XSS 偷 token | 需后端配合设置,前后端都要处理 |
建议:
- 大部分前后端分离项目:用 localStorage,配合 XSS 防护(输入过滤、CSP 等)。
- 对安全要求高的项目:用 HttpOnly cookie,由后端设置。
- 仅当前 tab 有效的临时 token:用 sessionStorage。
示例(localStorage 存 token):
// 登录成功后
const token = response.data.token;
localStorage.setItem('token', token);
// 请求拦截器里
axios.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// 退出登录
localStorage.removeItem('token');
6.2 用户配置(主题、语言等)
这类配置需要持久化,且希望下次打开还是同样的,用 localStorage:
// 封装一个简单的配置管理
const CONFIG_KEY = 'userConfig';
const defaultConfig = {
theme: 'light',
lang: 'zh',
sidebarCollapsed: false
};
function getConfig() {
try {
const saved = localStorage.getItem(CONFIG_KEY);
return saved ? { ...defaultConfig, ...JSON.parse(saved) } : { ...defaultConfig };
} catch {
return { ...defaultConfig };
}
}
function setConfig(partial) {
const config = { ...getConfig(), ...partial };
localStorage.setItem(CONFIG_KEY, JSON.stringify(config));
return config;
}
// 使用
setConfig({ theme: 'dark' });
const config = getConfig();
6.3 缓存查询条件(表格筛选、分页)
列表的筛选、排序、分页希望刷新后还能保留,用 localStorage:
const CACHE_KEY = 'userList_query';
// 进入页面时恢复
const savedQuery = JSON.parse(localStorage.getItem(CACHE_KEY) || '{}');
this.filters = savedQuery.filters || {};
this.pagination = savedQuery.pagination || { page: 1, size: 10 };
// 筛选或分页变化时保存
function saveQuery(filters, pagination) {
localStorage.setItem(CACHE_KEY, JSON.stringify({
filters,
pagination
}));
}
// 清空筛选时清除
function clearQuery() {
localStorage.removeItem(CACHE_KEY);
}
6.4 多步表单的中间状态
多步表单的中间页,只对当前 tab 有效,不希望跨 tab 共享,用 sessionStorage:
// 第二步填写时保存
sessionStorage.setItem('formStep2', JSON.stringify(formData));
// 第三步页面加载时恢复
const step2Data = JSON.parse(sessionStorage.getItem('formStep2') || '{}');
// 提交成功后清除
sessionStorage.removeItem('formStep2');
七、怎么选?一张表搞定
| 场景 | 推荐 | 理由 |
|---|---|---|
| Token | localStorage 或 HttpOnly cookie | 持久、跨 tab;安全要求高用 cookie |
| 用户主题、语言、配置 | localStorage | 持久化,刷新和重开都保留 |
| 列表筛选、分页、排序 | localStorage | 持久化,提升使用体验 |
| 多步表单中间状态 | sessionStorage | 仅当前 tab,关掉即清空 |
| 临时防重复提交标记 | sessionStorage | 仅当前会话有效 |
| 需要随请求自动携带的凭证 | cookie | 浏览器会自动带上 |
八、踩坑指南
| 坑 | 原因 | 建议 |
|---|---|---|
| 存对象报错或乱码 | 只支持字符串 | 用 JSON.stringify 存,JSON.parse 取 |
| 私密模式下 localStorage 可能不可用 | 部分浏览器会限制或清空 | 用 try-catch 包一层,失败时降级到内存 |
| 跨 tab 不同步 | localStorage 变更不会自动通知其他 tab | 监听 storage 事件做同步 |
| cookie 超出 4KB | 单条 cookie 约 4KB 限制 | 大对象改用 localStorage,或拆分多个 cookie |
| 测试环境数据残留 | 上次测试数据还在 | 测试前 localStorage.clear() 或单独用测试 key |
storage 事件:跨 tab 同步
当其他 tab 修改了 localStorage,当前 tab 会触发 storage 事件:
window.addEventListener('storage', (e) => {
if (e.key === 'theme') {
// 其他 tab 改了 theme,这里同步更新
applyTheme(e.newValue);
}
});
注意:修改 localStorage 的那个 tab 不会触发,只有其他同源页面会收到。
九、小结
| 存储方式 | 一句话 | 典型场景 |
|---|---|---|
| localStorage | 持久、同源共享、不随请求发送 | 用户配置、token、列表筛选缓存 |
| sessionStorage | 当前标签页有效、关掉即丢 | 多步表单、临时标记 |
| cookie | 容量小、随请求自动携带 | 需后端校验的登录凭证 |
记住三点:
- 需要持久化、跨 tab 用 localStorage;仅当前 tab、关掉就丢 用 sessionStorage。
- 需要随请求自动携带 用 cookie;否则优先用 localStorage/sessionStorage。
- 只存字符串,对象用
JSON.stringify/parse;注意容量(localStorage 约 5MB,cookie 约 4KB)。
选对存储方式,可以少很多莫名其妙的 bug,也更符合安全和性能预期。
学习本就是一场持久战,不需要急着一口吃成胖子。哪怕今天你只记住了一点点,这都是实打实的进步。
后续我还会继续用这种大白话、讲实战方式,带大家扫盲更多前端基础。
关注我,不迷路,咱们把那些曾经模糊的知识点,一个个彻底搞清楚。
如果你觉得这篇内容对你有帮助,不妨点赞收藏,下次写代码卡壳时,拿出来翻一翻,比搜引擎更靠谱。
我是 Eugene,你的电子学友,我们下一篇干货见~