浏览器存储
浏览器提供了在用户设备上保存数据的能力——主题偏好、登录状态、草稿内容等可以跨页面甚至跨会话保持。
localStorage — 持久存储
数据保存在浏览器中,除非手动清除,否则永远不会过期。关闭标签页、重启浏览器都不会丢失:
javascript
// 写入(值为字符串)
localStorage.setItem('username', '张三');
localStorage.setItem('theme', 'dark');
// 读取
const username = localStorage.getItem('username');
console.log(username); // "张三"
// 删除单个
localStorage.removeItem('theme');
// 清空全部
localStorage.clear();
// 获取键名(按索引)
console.log(localStorage.key(0)); // 第一个键名
// 总条数
console.log(localStorage.length); 存储对象和数组
localStorage 只能存字符串,存储复杂数据需要 JSON 转换:
javascript
const user = { name: '张三', age: 25, settings: { theme: 'dark' } };
// 存储
localStorage.setItem('user', JSON.stringify(user));
// 读取(注意:key 不存在时 getItem 返回 null)
const saved = JSON.parse(localStorage.getItem('user'));
console.log(saved?.name); // "张三",key 不存在时为 undefined sessionStorage — 会话存储
用法与 localStorage 完全相同,区别在于数据在关闭标签页后自动清除:
javascript
// 存储敏感或临时的会话数据
sessionStorage.setItem('authToken', 'abc123');
// 读取
const token = sessionStorage.getItem('authToken'); 刷新页面数据还在,关闭标签页或浏览器则数据丢失。
localStorage vs sessionStorage vs Cookie
| 特性 | localStorage | sessionStorage | Cookie |
|---|---|---|---|
| 容量 | ~5-10MB | ~5-10MB | ~4KB |
| 生命周期 | 永久 | 标签页关闭 | 可设置过期时间 |
| 随请求发送到服务器 | 否 | 否 | 是(自动) |
| 作用域 | 同源 | 同源 + 同标签页 | 同源 + 可设 path |
| API | 简单 | 简单 | 操作繁琐 |
| 适合场景 | 用户偏好、缓存 | 表单暂存、临时状态 | 身份验证、跟踪 |
简单选择:需要服务器读取的数据(如登录 token)用 Cookie;不需要服务器参与的本地数据用 localStorage(持久)或 sessionStorage(会话)。
监听存储变化
storage 事件在其他标签页修改 localStorage 时触发(同一标签页不触发):
javascript
window.addEventListener('storage', (event) => {
console.log(`键 "${event.key}" 被修改`);
console.log(`旧值:${event.oldValue}`);
console.log(`新值:${event.newValue}`);
// 可用于跨标签页同步数据(如多标签页同时登出)
}); 存储满时处理
javascript
try {
localStorage.setItem('key', 'value');
} catch (error) {
if (error.name === 'QuotaExceededError') {
console.log('存储空间已满,请清理旧数据');
}
} 实际应用示例
用户偏好保存
javascript
const themeToggle = document.querySelector('#theme-toggle');
// 读取已保存主题
const savedTheme = localStorage.getItem('theme') || 'light';
document.body.dataset.theme = savedTheme;
// 切换并保存
themeToggle.addEventListener('click', () => {
const current = document.body.dataset.theme;
const next = current === 'light' ? 'dark' : 'light';
document.body.dataset.theme = next;
localStorage.setItem('theme', next);
}); 表单草稿自动保存
javascript
const form = document.querySelector('#post-form');
// 恢复草稿
const savedDraft = sessionStorage.getItem('draft');
if (savedDraft) {
form.querySelector('textarea').value = savedDraft;
}
// 自动保存(每次输入时)
form.addEventListener('input', () => {
const content = form.querySelector('textarea').value;
sessionStorage.setItem('draft', content);
});
// 提交后清除
form.addEventListener('submit', () => {
sessionStorage.removeItem('draft');
});