7.1 Web Storage(localStorage/sessionStorage)
7.1 Web Storage (localStorage/sessionStorage)
Web Storage API 是现代浏览器提供的客户端存储解决方案,包含两种主要机制:localStorage 和 sessionStorage。这两种存储方式为前端开发提供了简单、高效的键值对存储能力,克服了传统cookie的诸多限制。
核心特性对比
| 特性 | localStorage | sessionStorage |
|---|---|---|
| 生命周期 | 永久存储,除非手动清除 | 会话级别存储,标签页关闭时清除 |
| 作用域 | 同源下所有标签页共享 | 仅限当前标签页 |
| 存储限额 | 通常5MB-10MB(各浏览器不同) | 同localStorage |
| 数据格式 | 仅支持字符串 | 同localStorage |
| 访问方式 | 同步操作 | 同localStorage |
| 适用场景 | 长期偏好设置、离线数据 | 临时表单数据、页面间传参 |
基本操作指南
1. 存储数据
// localStorage 示例
localStorage.setItem('theme', 'dark'); // 存储字符串
localStorage.setItem('user', JSON.stringify({ // 存储对象需要序列化
id: 123,
name: 'John Doe'
}));
// sessionStorage 示例
sessionStorage.setItem('formDraft', JSON.stringify({
username: '',
email: '',
preferences: {}
}));
2. 读取数据
// 读取简单值
const theme = localStorage.getItem('theme'); // "dark"
// 读取对象
const userStr = localStorage.getItem('user');
const user = userStr ? JSON.parse(userStr) : null;
// 检查sessionStorage中的临时数据
const draft = sessionStorage.getItem('formDraft');
if (draft) {
formState = JSON.parse(draft);
}
3. 删除数据
// 移除单个项
localStorage.removeItem('theme');
// 清空所有存储
sessionStorage.clear();
// 注意:clear()会移除同源下的所有数据,慎用
高级使用技巧
1. 存储事件监听
当同源下的其他标签页修改存储时,可以监听变化:
window.addEventListener('storage', (event) => {
console.log(`键 ${event.key} 发生变化`);
console.log(`旧值: ${event.oldValue}`);
console.log(`新值: ${event.newValue}`);
console.log(`来源: ${event.url}`);
// 主题切换示例
if (event.key === 'theme') {
document.body.className = event.newValue;
}
});
2. 容量检测与处理
function testStorageQuota() {
const testKey = 'quotaTest';
const testData = new Array(1024 * 1024).join('a'); // 1MB数据
try {
localStorage.setItem(testKey, testData);
localStorage.removeItem(testKey);
return true;
} catch (e) {
if (e.name === 'QuotaExceededError') {
console.warn('存储空间不足');
// 执行清理逻辑
clearOldCache();
return false;
}
}
}
function clearOldCache() {
// 按时间戳清理旧数据
const now = Date.now();
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith('cache_')) {
const data = JSON.parse(localStorage.getItem(key));
if (now - data.timestamp > 30 * 24 * 60 * 60 * 1000) { // 30天前
localStorage.removeItem(key);
}
}
}
}
3. 命名空间管理
// 创建命名空间类
class AppStorage {
constructor(namespace) {
this.ns = namespace + ':';
}
set(key, value) {
localStorage.setItem(this.ns + key, JSON.stringify(value));
}
get(key) {
const data = localStorage.getItem(this.ns + key);
return data ? JSON.parse(data) : null;
}
getAll() {
const items = {};
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith(this.ns)) {
const realKey = key.slice(this.ns.length);
items[realKey] = this.get(realKey);
}
}
return items;
}
}
// 使用示例
const userStorage = new AppStorage('user_prefs');
userStorage.set('theme', { mode: 'dark', accent: '#ff5722' });
const prefs = userStorage.getAll();
实际应用场景
1. 用户偏好设置
// 保存主题偏好
function saveThemePreference(theme) {
localStorage.setItem('app:theme', JSON.stringify({
mode: theme,
lastUpdated: new Date().toISOString()
}));
}
// 初始化时应用主题
function applySavedTheme() {
const saved = localStorage.getItem('app:theme');
if (saved) {
const { mode } = JSON.parse(saved);
document.documentElement.setAttribute('data-theme', mode);
}
}
2. 表单自动保存
// 监听表单变化
const form = document.getElementById('settings-form');
form.addEventListener('input', debounce(() => {
const formData = new FormData(form);
const data = Object.fromEntries(formData);
sessionStorage.setItem('formAutosave', JSON.stringify(data));
}, 500));
// 页面加载时恢复
window.addEventListener('DOMContentLoaded', () => {
const saved = sessionStorage.getItem('formAutosave');
if (saved) {
const data = JSON.parse(saved);
for (const [name, value] of Object.entries(data)) {
if (form.elements[name]) {
form.elements[name].value = value;
}
}
}
});
3. 购物车临时存储
class CartService {
static KEY = 'cart_v2';
static getItems() {
const cart = sessionStorage.getItem(this.KEY);
return cart ? JSON.parse(cart) : [];
}
static addItem(product) {
const items = this.getItems();
const existing = items.find(item => item.id === product.id);
if (existing) {
existing.quantity += 1;
} else {
items.push({ ...product, quantity: 1 });
}
sessionStorage.setItem(this.KEY, JSON.stringify(items));
this.dispatchUpdate();
}
static dispatchUpdate() {
window.dispatchEvent(new CustomEvent('cartUpdated', {
detail: this.getItems()
}));
}
}
// 使用示例
CartService.addItem({ id: 101, name: 'Web开发指南', price: 99 });
window.addEventListener('cartUpdated', (e) => {
updateCartUI(e.detail);
});
安全注意事项
-
XSS攻击风险:
- 永远不要存储敏感信息(如密码、令牌)
- 对存储的数据进行消毒处理
-
数据验证:
function getSafeConfig() { try { const config = JSON.parse(localStorage.getItem('appConfig')); if (config && typeof config === 'object') { return sanitize(config); // 实现数据消毒逻辑 } } catch (e) { console.error('配置解析失败', e); } return getDefaultConfig(); } -
隐私合规:
- GDPR等法规要求
- 提供清除数据的选项
<button id="clearData">清除我的本地数据</button> <script> document.getElementById('clearData').addEventListener('click', () => { if (confirm('确定要清除所有本地存储数据吗?')) { localStorage.clear(); sessionStorage.clear(); } }); </script>
性能优化策略
-
批量操作:
function batchSaveItems(items) { const batch = {}; items.forEach(item => { batch[`item_${item.id}`] = item; }); localStorage.setItem('itemBatch', JSON.stringify(batch)); } -
数据压缩:
function compressSave(key, data) { const str = JSON.stringify(data); // 简单base64压缩(实际项目可使用lz-string等库) localStorage.setItem(key, btoa(unescape(encodeURIComponent(str)))); } function compressLoad(key) { const compressed = localStorage.getItem(key); if (!compressed) return null; try { return JSON.parse(decodeURIComponent(escape(atob(compressed)))); } catch (e) { return null; } } -
过期策略:
function setWithExpiry(key, value, expiryDays) { const item = { value: value, expiry: Date.now() + (expiryDays * 24 * 60 * 60 * 1000) }; localStorage.setItem(key, JSON.stringify(item)); } function getWithExpiry(key) { const itemStr = localStorage.getItem(key); if (!itemStr) return null; const item = JSON.parse(itemStr); if (Date.now() > item.expiry) { localStorage.removeItem(key); return null; } return item.value; }
现代浏览器的替代方案
虽然Web Storage简单易用,但对于更复杂的场景,可以考虑:
-
IndexedDB:
- 更大的存储空间
- 支持事务和索引查询
- 适合结构化数据
-
Cache API:
- 专为网络资源设计
- 配合Service Worker使用
- 实现离线应用
-
Web SQL(已废弃):
- 虽然被大多数浏览器支持
- 但已被W3C废弃,不推荐新项目使用
Web Storage作为浏览器存储的基石,在适当的场景下仍然是简单高效的选择。理解其特性和限制,能够帮助开发者在各种存储方案中做出合理决策。
#前端开发
分享于 2025-05-20
上一篇:6.5 WebGL 简介
下一篇:7.2 IndexedDB 基础