现代 Web 开发中,主要有以下几种客户端存储技术:
| 特性 | Cookie | localStorage | sessionStorage | IndexedDB |
|---|---|---|---|---|
| 引入时间 | 早期 (HTTP 1.0) | HTML5 | HTML5 | HTML5 |
| 数据生命周期 | 可设置过期时间,否则随会话结束 | 永久存储,除非手动清除 | 仅限当前会话,关闭标签页即清除 | 永久存储,除非手动清除 |
| 存储容量 | 约 4KB | 约 5MB (因浏览器而异) | 约 5MB (因浏览器而异) | 巨大 (通常 ≥250MB,甚至更多) |
| 与服务器的交互 | 每次都会在 HTTP 请求头(Cookie)中携带,影响性能 | 仅存储在客户端,不参与服务器通信 | 仅存储在客户端,不参与服务器通信 | 仅存储在客户端,不参与服务器通信 |
| 数据类型 | 字符串 | 字符串 | 字符串 | 任何 JavaScript 类型(对象、数组、文件等) |
| API 易用性 | 简单,但需自行处理字符串 | 非常简单的键值对 API | 非常简单的键值对 API | 复杂,基于事务的异步 API |
| 主要用途 | 会话管理、用户标识、个性化 | 长期持久化数据(如用户偏好、购物车) | 临时会话数据(如表单内容、单次浏览信息) | 存储大量结构化数据、离线 Web 应用 |
Cookie 是最早的客户端存储解决方案,最初设计用于在客户端存储会话标识符,以便服务器能够识别用户状态。
特点:
基本操作:
// 设置 Cookie
document.cookie = "username=John Doe; max-age=3600; path=/";
// 读取 Cookie
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(";").shift();
}
console.log(getCookie("username")); // 输出 "John Doe"
特点:
基本操作:
// 存储数据
localStorage.setItem("theme", "dark");
localStorage.setItem("user", JSON.stringify({ name: "Alice", id: 1 })); // 存对象需转成字符串
// 读取数据
const theme = localStorage.getItem("theme"); // 'dark'
const user = JSON.parse(localStorage.getItem("user")); // { name: 'Alice', id: 1 }
// 删除单个数据
localStorage.removeItem("theme");
// 清空所有数据
localStorage.clear();
// 获取键名
const key = localStorage.key(0); // 获取第一个键名
特点:
API 与 localStorage 完全相同,只是对象名换成了 sessionStorage。
// 存储数据
sessionStorage.setItem("theme", "dark");
sessionStorage.setItem("user", JSON.stringify({ name: "Alice", id: 1 })); // 存对象需转成字符串
// 读取数据
const theme = sessionStorage.getItem("theme"); // 'dark'
const user = JSON.parse(sessionStorage.getItem("user")); // { name: 'Alice', id: 1 }
// 删除单个数据
sessionStorage.removeItem("theme");
// 清空所有数据
sessionStorage.clear();
// 获取键名
const key = sessionStorage.key(0); // 获取第一个键名
当需要存储大量结构化数据(如客户记录、产品目录)或进行复杂查询时,localStorage 就力不从心了。这时需要使用 IndexedDB。
特点:
基本操作示例(打开数据库并添加数据):
// 打开或创建数据库
const request = indexedDB.open("MyTestDB", 1); // 数据库名,版本号
request.onerror = event => {
console.error("为什么我的 IndexedDB 出错啦!", event);
};
request.onsuccess = event => {
const db = event.target.result;
console.log("数据库打开成功!");
// 在这里执行数据库操作
};
// 如果数据库版本升级(或第一次创建),会触发 onupgradeneeded 事件
request.onupgradeneeded = event => {
const db = event.target.result;
// 创建一个对象存储空间(类似于 SQL 的表),并定义主键
const objectStore = db.createObjectStore("customers", { keyPath: "id", autoIncrement: true });
// 创建索引
objectStore.createIndex("name", "name", { unique: false });
};
// 在 onsuccess 中,添加一条数据
function addCustomer(db, customer) {
// 创建一个读写事务
const transaction = db.transaction(["customers"], "readwrite");
// 获取对象存储空间
const objectStore = transaction.objectStore("customers");
// 添加数据
const request = objectStore.add(customer);
request.onsuccess = event => {
console.log("数据已添加,ID:", event.target.result);
};
}