浏览器存储方案
Cookie、localStorage、sessionStorage、IndexedDB 的对比与使用
问题
浏览器有哪些存储方案?它们的区别和使用场景是什么?
解答
Cookie
// 设置 cookie
document.cookie = 'username=john; max-age=3600; path=/';
// 设置带过期时间的 cookie
document.cookie = 'token=abc123; expires=Thu, 01 Jan 2025 00:00:00 GMT';
// 读取所有 cookie
console.log(document.cookie); // "username=john; token=abc123"
// 封装 cookie 操作
const Cookie = {
set(name, value, days) {
let expires = '';
if (days) {
const date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
expires = `; expires=${date.toUTCString()}`;
}
document.cookie = `${name}=${encodeURIComponent(value)}${expires}; path=/`;
},
get(name) {
const cookies = document.cookie.split('; ');
for (const cookie of cookies) {
const [key, val] = cookie.split('=');
if (key === name) return decodeURIComponent(val);
}
return null;
},
remove(name) {
this.set(name, '', -1);
}
};
localStorage
// 存储数据
localStorage.setItem('user', JSON.stringify({ name: 'john', age: 25 }));
// 读取数据
const user = JSON.parse(localStorage.getItem('user'));
// 删除数据
localStorage.removeItem('user');
// 清空所有数据
localStorage.clear();
// 封装 localStorage,支持过期时间
const Storage = {
set(key, value, expireMinutes) {
const data = {
value,
expire: expireMinutes ? Date.now() + expireMinutes * 60 * 1000 : null
};
localStorage.setItem(key, JSON.stringify(data));
},
get(key) {
const item = localStorage.getItem(key);
if (!item) return null;
const data = JSON.parse(item);
// 检查是否过期
if (data.expire && Date.now() > data.expire) {
localStorage.removeItem(key);
return null;
}
return data.value;
}
};
sessionStorage
// API 与 localStorage 完全相同
sessionStorage.setItem('tempData', 'hello');
sessionStorage.getItem('tempData');
sessionStorage.removeItem('tempData');
sessionStorage.clear();
// 区别:关闭标签页后数据清除
IndexedDB
// 打开数据库
const request = indexedDB.open('myDB', 1);
// 数据库升级时创建表
request.onupgradeneeded = (event) => {
const db = event.target.result;
// 创建对象仓库(表),keyPath 是主键
const store = db.createObjectStore('users', { keyPath: 'id' });
// 创建索引
store.createIndex('name', 'name', { unique: false });
};
request.onsuccess = (event) => {
const db = event.target.result;
// 添加数据
const tx = db.transaction('users', 'readwrite');
const store = tx.objectStore('users');
store.add({ id: 1, name: 'john', email: 'john@example.com' });
// 读取数据
const getRequest = store.get(1);
getRequest.onsuccess = () => {
console.log(getRequest.result);
};
};
// 封装为 Promise
class IDB {
constructor(dbName, storeName) {
this.dbName = dbName;
this.storeName = storeName;
}
open() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, 1);
request.onupgradeneeded = (e) => {
e.target.result.createObjectStore(this.storeName, { keyPath: 'id' });
};
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async add(data) {
const db = await this.open();
const tx = db.transaction(this.storeName, 'readwrite');
tx.objectStore(this.storeName).add(data);
}
async get(id) {
const db = await this.open();
return new Promise((resolve) => {
const request = db.transaction(this.storeName).objectStore(this.storeName).get(id);
request.onsuccess = () => resolve(request.result);
});
}
}
对比表格
| 特性 | Cookie | localStorage | sessionStorage | IndexedDB |
|---|---|---|---|---|
| 容量 | 4KB | 5-10MB | 5-10MB | 无限制 |
| 过期 | 可设置 | 永久 | 标签页关闭 | 永久 |
| 服务端访问 | 自动携带 | 否 | 否 | 否 |
| API | 字符串操作 | 同步 | 同步 | 异步 |
| 数据类型 | 字符串 | 字符串 | 字符串 | 任意 |
关键点
- Cookie:容量小(4KB),会随请求发送到服务端,适合存储身份认证信息
- localStorage:容量大,永久存储,同源共享,适合存储用户偏好设置
- sessionStorage:仅当前标签页有效,适合存储临时表单数据
- IndexedDB:异步操作,支持事务和索引,适合存储大量结构化数据
- 选择原则:小数据用 localStorage,需要服务端读取用 Cookie,大数据或复杂查询用 IndexedDB
目录