跳到主要内容

浏览器存储

概述

浏览器存储是Web应用中不可或缺的一部分,它允许应用在客户端存储数据,实现状态管理、用户偏好设置、离线功能等。现代浏览器提供了多种存储机制,每种机制都有其特定的用途、优势和限制。选择合适的存储方案对于提升应用性能和用户体验至关重要。

核心存储机制

1. 存储机制对比

存储机制对比:

存储类型大小限制生命周期同步/异步主要用途兼容性
Cookie4KB可设置过期时间同步身份认证、会话管理所有浏览器
LocalStorage5-10MB永久存储同步用户偏好、应用状态现代浏览器
SessionStorage5-10MB会话期间同步临时数据、表单状态现代浏览器
IndexedDB无限制永久存储异步复杂数据、离线应用现代浏览器
Cache API无限制可控制异步网络资源缓存现代浏览器

存储机制选择决策树:

2. 存储机制特点

存储机制特点图示:

技术实现方案

1. Cookie存储

Cookie基础操作:

// Cookie管理器
class CookieManager {
// 设置Cookie
static set(name, value, options = {}) {
let cookieString = `${name}=${encodeURIComponent(value)}`;

if (options.expires) {
cookieString += `; expires=${options.expires.toUTCString()}`;
}

if (options.maxAge) {
cookieString += `; max-age=${options.maxAge}`;
}

if (options.path) {
cookieString += `; path=${options.path}`;
}

if (options.domain) {
cookieString += `; domain=${options.domain}`;
}

if (options.secure) {
cookieString += `; secure`;
}

if (options.sameSite) {
cookieString += `; samesite=${options.sameSite}`;
}

document.cookie = cookieString;
}

// 获取Cookie
static get(name) {
const cookies = document.cookie.split(';');

for (let cookie of cookies) {
const [cookieName, cookieValue] = cookie.trim().split('=');
if (cookieName === name) {
return decodeURIComponent(cookieValue);
}
}

return null;
}

// 删除Cookie
static delete(name, options = {}) {
this.set(name, '', {
...options,
expires: new Date(0)
});
}

// 获取所有Cookie
static getAll() {
const cookies = {};
const cookieArray = document.cookie.split(';');

for (let cookie of cookieArray) {
const [name, value] = cookie.trim().split('=');
if (name && value) {
cookies[name] = decodeURIComponent(value);
}
}

return cookies;
}
}

// 使用示例
CookieManager.set('username', 'John Doe', {
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7天
path: '/',
secure: true,
sameSite: 'strict'
});

const username = CookieManager.get('username');
console.log('用户名:', username);

2. LocalStorage存储

LocalStorage管理器:

// LocalStorage管理器
class LocalStorageManager {
// 存储数据
static set(key, value) {
try {
const serializedValue = JSON.stringify(value);
localStorage.setItem(key, serializedValue);
return true;
} catch (error) {
console.error('LocalStorage存储失败:', error);
return false;
}
}

// 获取数据
static get(key, defaultValue = null) {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : defaultValue;
} catch (error) {
console.error('LocalStorage读取失败:', error);
return defaultValue;
}
}

// 删除数据
static remove(key) {
try {
localStorage.removeItem(key);
return true;
} catch (error) {
console.error('LocalStorage删除失败:', error);
return false;
}
}

// 清空所有数据
static clear() {
try {
localStorage.clear();
return true;
} catch (error) {
console.error('LocalStorage清空失败:', error);
return false;
}
}

// 获取存储大小
static getSize() {
let total = 0;
for (let key in localStorage) {
if (localStorage.hasOwnProperty(key)) {
total += localStorage[key].length + key.length;
}
}
return total;
}

// 检查是否支持
static isSupported() {
try {
const test = '__localStorage_test__';
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch (error) {
return false;
}
}
}

// 使用示例
if (LocalStorageManager.isSupported()) {
LocalStorageManager.set('userSettings', {
theme: 'dark',
language: 'zh-CN',
notifications: true
});

const settings = LocalStorageManager.get('userSettings');
console.log('用户设置:', settings);
}

3. SessionStorage存储

SessionStorage管理器:

// SessionStorage管理器
class SessionStorageManager {
// 存储数据
static set(key, value) {
try {
const serializedValue = JSON.stringify(value);
sessionStorage.setItem(key, serializedValue);
return true;
} catch (error) {
console.error('SessionStorage存储失败:', error);
return false;
}
}

// 获取数据
static get(key, defaultValue = null) {
try {
const item = sessionStorage.getItem(key);
return item ? JSON.parse(item) : defaultValue;
} catch (error) {
console.error('SessionStorage读取失败:', error);
return defaultValue;
}
}

// 删除数据
static remove(key) {
try {
sessionStorage.removeItem(key);
return true;
} catch (error) {
console.error('SessionStorage删除失败:', error);
return false;
}
}

// 清空所有数据
static clear() {
try {
sessionStorage.clear();
return true;
} catch (error) {
console.error('SessionStorage清空失败:', error);
return false;
}
}
}

// 使用示例
SessionStorageManager.set('formData', {
name: 'John Doe',
email: 'john@example.com',
message: 'Hello World'
});

const formData = SessionStorageManager.get('formData');
console.log('表单数据:', formData);

4. IndexedDB存储

IndexedDB管理器:

// IndexedDB管理器
class IndexedDBManager {
constructor(dbName, version = 1) {
this.dbName = dbName;
this.version = version;
this.db = null;
}

// 打开数据库
async open() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, this.version);

request.onsuccess = (event) => {
this.db = event.target.result;
resolve(this.db);
};

request.onerror = (event) => {
reject(event.target.error);
};

request.onupgradeneeded = (event) => {
const db = event.target.result;

// 创建对象存储
if (!db.objectStoreNames.contains('users')) {
const userStore = db.createObjectStore('users', { keyPath: 'id' });
userStore.createIndex('email', 'email', { unique: true });
}

if (!db.objectStoreNames.contains('settings')) {
db.createObjectStore('settings', { keyPath: 'key' });
}
};
});
}

// 添加数据
async add(storeName, data) {
const transaction = this.db.transaction([storeName], 'readwrite');
const store = transaction.objectStore(storeName);

return new Promise((resolve, reject) => {
const request = store.add(data);

request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}

// 获取数据
async get(storeName, key) {
const transaction = this.db.transaction([storeName], 'readonly');
const store = transaction.objectStore(storeName);

return new Promise((resolve, reject) => {
const request = store.get(key);

request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}

// 更新数据
async update(storeName, data) {
const transaction = this.db.transaction([storeName], 'readwrite');
const store = transaction.objectStore(storeName);

return new Promise((resolve, reject) => {
const request = store.put(data);

request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}

// 删除数据
async delete(storeName, key) {
const transaction = this.db.transaction([storeName], 'readwrite');
const store = transaction.objectStore(storeName);

return new Promise((resolve, reject) => {
const request = store.delete(key);

request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}

// 获取所有数据
async getAll(storeName) {
const transaction = this.db.transaction([storeName], 'readonly');
const store = transaction.objectStore(storeName);

return new Promise((resolve, reject) => {
const request = store.getAll();

request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
}

// 使用示例
const dbManager = new IndexedDBManager('MyAppDB', 1);

// 打开数据库
dbManager.open().then(() => {
// 添加用户
return dbManager.add('users', {
id: 1,
name: 'John Doe',
email: 'john@example.com'
});
}).then(() => {
// 获取用户
return dbManager.get('users', 1);
}).then(user => {
console.log('用户信息:', user);
}).catch(error => {
console.error('数据库操作失败:', error);
});

5. Cache API存储

Cache API管理器:

// Cache API管理器
class CacheManager {
constructor(cacheName) {
this.cacheName = cacheName;
}

// 打开缓存
async open() {
return await caches.open(this.cacheName);
}

// 添加资源到缓存
async add(url) {
const cache = await this.open();
return await cache.add(url);
}

// 添加多个资源到缓存
async addAll(urls) {
const cache = await this.open();
return await cache.addAll(urls);
}

// 获取缓存的响应
async get(request) {
const cache = await this.open();
return await cache.match(request);
}

// 添加响应到缓存
async put(request, response) {
const cache = await this.open();
return await cache.put(request, response);
}

// 删除缓存
async delete(request) {
const cache = await this.open();
return await cache.delete(request);
}

// 获取所有缓存的键
async keys() {
const cache = await this.open();
return await cache.keys();
}

// 清空缓存
async clear() {
const cache = await this.open();
return await cache.clear();
}
}

// 使用示例
const cacheManager = new CacheManager('my-app-cache');

// 缓存资源
cacheManager.addAll([
'/',
'/index.html',
'/styles.css',
'/app.js',
'/images/logo.png'
]).then(() => {
console.log('资源缓存成功');
}).catch(error => {
console.error('缓存失败:', error);
});

// 获取缓存的响应
cacheManager.get('/index.html').then(response => {
if (response) {
console.log('从缓存获取资源');


<!-- Mermaid图表缩放控制 -->
<div className="mermaid-controls" data-chart-section="chart-2">
<button className="mermaid-zoom-btn" title="放大">
<span className="zoom-icon">🔍+</span>
</button>
<button className="mermaid-zoom-btn" title="缩小">
<span className="zoom-icon">🔍-</span>
</button>
<button className="mermaid-zoom-btn" title="重置">
<span className="zoom-icon">🔄</span>
</button>
<button className="mermaid-zoom-btn" title="全屏">
<span className="zoom-icon"></span>
</button>
</div>} else {
console.log('资源未缓存');
}
});

存储策略

1. 存储策略选择

存储策略图示:

2. 存储策略实现

统一存储管理器:

// 统一存储管理器
class StorageManager {
constructor() {
this.storages = {
cookie: new CookieManager(),
localStorage: new LocalStorageManager(),
sessionStorage: new SessionStorageManager(),
indexedDB: new IndexedDBManager('AppDB')
};
}

// 根据数据类型选择存储方式
getStorage(type, size) {
if (type === 'auth' || type === 'session') {
return this.storages.cookie;
} else if (type === 'userPrefs' && size < 10 * 1024 * 1024) {
return this.storages.localStorage;
} else if (type === 'temp' && size < 10 * 1024 * 1024) {
return this.storages.sessionStorage;
} else {
return this.storages.indexedDB;
}
}

// 存储数据
async store(key, value, options = {}) {
const { type = 'userPrefs', size = 0, ...storageOptions } = options;
const storage = this.getStorage(type, size);

try {
if (storage === this.storages.indexedDB) {
await storage.open();
return await storage.add('data', { key, value });
} else {
return storage.set(key, value);
}
} catch (error) {
console.error('存储失败:', error);
return false;
}
}

// 获取数据
async retrieve(key, options = {}) {
const { type = 'userPrefs', size = 0 } = options;
const storage = this.getStorage(type, size);

try {
if (storage === this.storages.indexedDB) {
await storage.open();
const result = await storage.get('data', key);
return result ? result.value : null;
} else {
return storage.get(key);
}
} catch (error) {
console.error('获取数据失败:', error);
return null;
}
}

// 删除数据
async remove(key, options = {}) {
const { type = 'userPrefs', size = 0 } = options;
const storage = this.getStorage(type, size);

try {
if (storage === this.storages.

<!-- Mermaid图表缩放控制 -->
<div className="mermaid-controls" data-chart-section="chart-3">
<button className="mermaid-zoom-btn" title="放大">
<span className="zoom-icon">🔍+</span>
</button>
<button className="mermaid-zoom-btn" title="缩小">
<span className="zoom-icon">🔍-</span>
</button>
<button className="mermaid-zoom-btn" title="重置">
<span className="zoom-icon">🔄</span>
</button>
<button className="mermaid-zoom-btn" title="全屏">
<span className="zoom-icon"></span>
</button>
</div>indexedDB) {
await storage.open();
return await storage.delete('data', key);
} else {
return storage.remove(key);
}
} catch (error) {
console.error('删除数据失败:', error);
return false;
}
}
}

// 使用示例
const storageManager = new StorageManager();

// 存储用户认证信息
storageManager.store('authToken', 'abc123', { type: 'auth' });

// 存储用户偏好设置
storageManager.store('theme', 'dark', { type: 'userPrefs' });

// 存储临时数据
storageManager.store('formData', { name: 'John' }, { type: 'temp' });

// 存储大量数据
storageManager.store('largeData', largeObject, { type: 'cache', size: 1024 * 1024 });

性能优化

1. 存储性能优化

性能优化策略:

2. 性能优化实现

性能优化管理器:

// 性能优化管理器
class PerformanceOptimizedStorage {
constructor() {
this.writeQueue = [];
this.readCache = new Map();
this.isProcessing = false;
}

// 批量写入
async batchWrite(operations) {
this.writeQueue.push(...operations);

if (!this.isProcessing) {
await this.processQueue();
}
}

// 处理写入队列
async processQueue() {
this.isProcessing = true;

while (this.writeQueue.length > 0) {
const batch = this.writeQueue.splice(0, 10); // 每次处理10个操作

try {
await Promise.all(batch.map(op => this.executeOperation(op)));
} catch (error) {
console.error('批量写入失败:', error);
}
}

this.isProcessing = false;
}

// 执行单个操作
async executeOperation(operation) {
const { type, key, value } = operation;

switch

<!-- Mermaid图表缩放控制 -->
<div className="mermaid-controls" data-chart-section="chart-4">
<button className="mermaid-zoom-btn" title="放大">
<span className="zoom-icon">🔍+</span>
</button>
<button className="mermaid-zoom-btn" title="缩小">
<span className="zoom-icon">🔍-</span>
</button>
<button className="mermaid-zoom-btn" title="重置">
<span className="zoom-icon">🔄</span>
</button>
<button className="mermaid-zoom-btn" title="全屏">
<span className="zoom-icon"></span>
</button>
</div>(type) {
case 'set':
localStorage.setItem(key, JSON.stringify(value));
break;
case 'remove':
localStorage.removeItem(key);
break;
case 'clear':
localStorage.clear();
break;
}
}

// 带缓存的读取
async get(key) {
if (this.readCache.has(key)) {
return this.readCache.get(key);
}

const value = localStorage.getItem(key);
const parsedValue = value ? JSON.parse(value) : null;

this.readCache.set(key, parsedValue);
return parsedValue;
}

// 带缓存的写入
async set(key, value) {
this.writeQueue.push({ type: 'set', key, value });
this.readCache.set(key, value);

if (!this.isProcessing) {
await this.processQueue();
}
}

// 清理缓存
clearCache() {
this.readCache.clear();
}
}

// 使用示例
const optimizedStorage = new PerformanceOptimizedStorage();

// 批量写入数据
const operations = [
{ type: 'set', key: 'user1', value: { name: 'John' } },
{ type: 'set', key: 'user2', value: { name: 'Jane' } },
{ type: 'set', key: 'user3', value: { name: 'Bob' } }
];

optimizedStorage.batchWrite(operations);

最佳实践

1. 存储最佳实践

最佳实践原则:

2. 开发最佳实践

开发规范:

  1. 数据分类

    • 根据数据敏感性和大小选择合适的存储方式
    • 实现数据生命周期管理
    • 定期清理过期数据
  2. 安全防护

    • 对敏感数据进行加密存储
    • 使用HTTPS确保传输安全
    • 实现数据验证和访问控制
  3. 性能优化

    • 使用异步操作避免阻塞
    • 实现批量处理提高效率
    • 使用缓存减少重复操作
  4. 错误处理

    • 实现完善的错误处理机制
    • 提供降级方案
    • 监控存储操作状态

通过以上浏览器存储方案,可以构建出高效、安全、可靠的数据存储系统。