0%

web存储

Web 存储(localStorage & sessionStorage)详解:用法、区别与实战指南

Web 存储是浏览器提供的客户端数据存储方案,通过键值对(Key-Value)形式将数据保存在用户本地,仅允许存储该数据的网页(同源页面)访问,无需与服务器交互,适用于 “临时状态保存”“用户偏好设置”“离线数据缓存” 等场景。Web 存储主要分为 localStorage(本地存储)sessionStorage(会话存储) 两种,二者 API 相似但生命周期、作用范围差异显著。从 “核心区别→API 详解→实战场景→注意事项” 四个维度,全面讲解 Web 存储的使用方法与最佳实践

localStorage 与 sessionStorage 核心区别

在学习具体用法前,需先明确二者的核心差异,避免使用场景混淆:

对比维度 localStorage sessionStorage
数据生命周期 永久存储,无过期时间(除非手动删除或清除浏览器数据) 临时存储,仅在当前窗口 / 标签页生命周期内有效(关闭窗口 / 标签页后自动删除)
作用范围 同源页面共享(同一协议、域名、端口的所有窗口 / 标签页) 仅当前窗口 / 标签页独立(即使同源,新窗口 / 标签页也无法访问)
存储容量 约 5MB(不同浏览器略有差异,无统一标准) 约 5MB(与 localStorage 一致)
数据持久化 浏览器重启、设备重启后数据仍保留 窗口关闭或浏览器重启后数据丢失
适用场景 用户偏好设置(如主题、语言)、长期离线数据缓存 临时表单数据(如未提交的表单内容)、页面间临时状态传递

localStorage 详解:永久本地存储

localStorage 用于长久保存同源页面的共享数据,数据存储在浏览器的本地文件中(不同浏览器存储位置不同),除非手动删除,否则会一直保留(即使关闭浏览器、重启设备)。

1. 核心 API

localStorage 是 window 对象的属性,所有 API 均为同步操作(执行时会阻塞后续代码,需注意避免大量数据操作):

API 方法 作用描述 示例
localStorage.setItem(key, value) 保存数据(键和值均需为字符串类型,非字符串会自动转为字符串) localStorage.setItem("theme", "dark")
localStorage.getItem(key) 读取数据(若 key 不存在,返回 null const theme = localStorage.getItem("theme")
localStorage.removeItem(key) 删除指定 key 的数据(若 key 不存在,无任何操作) localStorage.removeItem("theme")
localStorage.clear() 删除当前域名下所有 localStorage 数据(谨慎使用,会清空所有键值对) localStorage.clear()
localStorage.key(index) 获取指定索引(从 0 开始)对应的 key(用于遍历所有数据) const firstKey = localStorage.key(0)
localStorage.length 只读属性,返回当前域名下 localStorage 的键值对数量(类似数组的 length const count = localStorage.length

2. 数据类型限制与处理

localStorage 仅支持字符串类型的键和值,若存储非字符串数据(如对象、数组、数字),需先通过 JSON.stringify() 转为 JSON 字符串,读取时再通过 JSON.parse() 转回原类型:

示例:存储 / 读取对象数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1. 定义非字符串数据(对象)
const userInfo = {
username: "zhangsan",
age: 25,
isVip: true
};

// 2. 存储:转为 JSON 字符串
localStorage.setItem("userInfo", JSON.stringify(userInfo));

// 3. 读取:从 JSON 字符串转回对象
const storedUserInfo = localStorage.getItem("userInfo");
const parsedUserInfo = storedUserInfo ? JSON.parse(storedUserInfo) : null;

console.log(parsedUserInfo.username); // 输出:"zhangsan"
console.log(parsedUserInfo.age); // 输出:25(数字类型,非字符串)
注意:
  • 若直接存储非字符串数据(如 localStorage.setItem("age", 25)),会自动转为字符串("25"),读取时需手动转为数字(Number(localStorage.getItem("age")));
  • JSON.stringify() 无法序列化 functionundefinedSymbol 等类型,存储包含这些类型的数据会导致丢失(需提前过滤)。

3. 适用场景

  • 用户偏好设置:保存用户选择的主题(如 theme: "dark")、语言(如 lang: "zh-CN")、字体大小等,下次打开页面时自动应用;
  • 离线数据缓存:缓存不常变化的静态数据(如商品分类列表、地区列表),减少服务器请求,提升离线访问体验;
  • 跨窗口状态同步:同源的多个窗口 / 标签页共享数据(如 A 窗口修改主题,B 窗口实时读取并应用新主题)。

sessionStorage 详解:临时会话存储

sessionStorage 用于临时保存当前窗口 / 标签页的私有数据,数据仅在当前窗口 / 标签页的生命周期内有效(关闭窗口、刷新页面不会丢失,但关闭标签页或浏览器后会自动删除),且不同窗口 / 标签页间数据不共享(即使同源)。

1. 核心 API(与 localStorage 基本一致)

sessionStorage 的 API 与 localStorage 完全相同,仅作用范围和生命周期不同:

API 方法 作用描述 示例
sessionStorage.setItem(key, value) 保存临时数据(键值均为字符串) sessionStorage.setItem("tempForm", "未提交")
sessionStorage.getItem(key) 读取临时数据(key 不存在返回 null const tempForm = sessionStorage.getItem("tempForm")
sessionStorage.removeItem(key) 删除指定 key 的临时数据 sessionStorage.removeItem("tempForm")
sessionStorage.clear() 删除当前窗口 / 标签页的所有 sessionStorage 数据 sessionStorage.clear()
sessionStorage.key(index) 获取指定索引的 key const firstKey = sessionStorage.key(0)
sessionStorage.length 返回当前窗口 / 标签页的键值对数量 const count = sessionStorage.length

2. 关键特性:窗口独立性

sessionStorage 的数据与窗口 / 标签页强绑定,即使是同源页面,不同窗口 / 标签页的 sessionStorage 数据完全独立:

  • 示例:在 Chrome 的 Tab1 中执行 sessionStorage.setItem("test", "tab1"),在 Tab2(同一域名)中执行 sessionStorage.getItem("test"),返回 null
  • 例外:通过 window.open() 打开的新窗口,若为 “父子窗口关系”(新窗口的 opener 指向父窗口),部分浏览器支持共享 sessionStorage(如 Firefox),但 Chrome、Edge 不支持,需避免依赖此特性。

3. 适用场景

  • 临时表单数据保存:用户填写长表单(如注册页、问卷)时,若不小心刷新页面,可通过 sessionStorage 恢复已输入的内容,避免数据丢失;
  • 页面间临时状态传递:同一窗口内,从页面 A 跳转到页面 B 时,传递临时参数(如 sessionStorage.setItem("fromPage", "A"),页面 B 读取后判断来源);
  • 敏感临时数据:保存仅当前会话有效的敏感数据(如临时令牌、验证码),关闭窗口后自动清除,降低安全风险。

实战场景:Web 存储的典型用法

场景 1:localStorage 保存用户主题偏好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!-- 主题切换按钮 -->
<button onclick="switchTheme('light')">浅色主题</button>
<button onclick="switchTheme('dark')">深色主题</button>

<script>
// 页面加载时,从 localStorage 读取主题并应用
window.addEventListener("DOMContentLoaded", function() {
// 读取主题(默认浅色主题)
const savedTheme = localStorage.getItem("theme") || "light";
applyTheme(savedTheme);
});

// 切换主题并保存到 localStorage
function switchTheme(theme) {
// 应用主题(修改页面样式)
applyTheme(theme);
// 保存主题到 localStorage
localStorage.setItem("theme", theme);
}

// 应用主题的具体逻辑
function applyTheme(theme) {
const body = document.body;
if (theme === "dark") {
body.style.backgroundColor = "#121212";
body.style.color = "#ffffff";
} else {
body.style.backgroundColor = "#ffffff";
body.style.color = "#333333";
}
}
</script>

场景 2:sessionStorage 保存临时表单数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<!-- 长表单 -->
<form id="longForm">
<div>
<label>用户名:</label>
<input type="text" name="username" id="username">
</div>
<div>
<label>邮箱:</label>
<input type="email" name="email" id="email">
</div>
<div>
<label>个人简介:</label>
<textarea name="intro" id="intro" rows="5"></textarea>
</div>
<button type="submit">提交</button>
</form>

<script>
const form = document.getElementById("longForm");
const formFields = form.querySelectorAll("input, textarea");

// 1. 页面加载时,从 sessionStorage 恢复表单数据
window.addEventListener("DOMContentLoaded", function() {
const savedFormData = sessionStorage.getItem("longFormData");
if (savedFormData) {
const formData = JSON.parse(savedFormData);
// 为每个字段赋值
formFields.forEach(field => {
if (formData[field.name]) {
field.value = formData[field.name];
}
});
}
});

// 2. 监听字段输入,实时保存到 sessionStorage
formFields.forEach(field => {
field.addEventListener("input", function() {
// 收集所有字段的当前值
const formData = {};
formFields.forEach(f => {
formData[f.name] = f.value;
});
// 保存到 sessionStorage
sessionStorage.setItem("longFormData", JSON.stringify(formData));
});
});

// 3. 表单提交成功后,清除 sessionStorage 中的临时数据
form.addEventListener("submit", function(e) {
e.preventDefault(); // 阻止默认提交(实际项目中替换为 AJAX 提交)

// 模拟表单提交成功
setTimeout(() => {
alert("表单提交成功!");
// 清除临时数据
sessionStorage.removeItem("longFormData");
form.reset(); // 重置表单
}, 1000);
});
</script>

重要注意事项与限制

1. 同源策略限制

Web 存储严格遵循同源策略:仅允许 “同一协议(http/https)、同一域名(如 example.com)、同一端口(如 80/443)” 的页面访问同一存储数据。跨域页面无法读取或修改对方的 Web 存储数据(即使是子域名,如 a.example.comb.example.com 也视为不同源,需通过 document.domain 特殊配置实现共享)。

2. 存储容量限制

  • 每个域名的 Web 存储容量约为 5MB(不同浏览器略有差异,如 Chrome 为 5MB,Firefox 为 10MB),超出容量会抛出 QuotaExceededError 异常;
  • 避免存储大量数据(如 base64 图片、大体积 JSON),建议仅存储轻量级数据(如配置、状态、小表单),大文件需使用 IndexedDB(浏览器提供的另一种大容量存储方案)。

3. 同步操作与性能风险

localStorage 和 sessionStorage 的所有 API 均为同步操作:执行时会阻塞 JavaScript 主线程,若存储 / 读取大量数据(如 1MB 以上的 JSON),会导致页面卡顿、响应延迟;

  • 解决方案:
    1. 拆分数据,避免一次性操作大量数据;
    2. 非关键数据的操作可放在 setTimeout 中,避免阻塞主线程;
    3. 大量数据存储优先使用 IndexedDB(异步操作,不阻塞主线程)。

4. 数据安全性风险

Web 存储的数据以明文形式存储在客户端,任何人可通过浏览器的 “开发者工具”(Application → Storage → Local Storage/Session Storage)查看或修改数据,因此:

  • 禁止存储敏感数据:如密码、令牌(Token)、银行卡号等,敏感数据需存储在服务器端,客户端仅存储临时授权凭证(如 JWT,且需设置过期时间);
  • 数据校验:从 Web 存储读取数据后,需进行合法性校验(如类型判断、字段验证),防止数据被篡改导致业务异常。

5. 浏览器兼容性

Web 存储支持所有现代浏览器(Chrome、Firefox、Edge、Safari 4+),但需注意:

  • IE 浏览器:仅支持 IE 8+,且 IE 8/9 的 localStorage 存在部分兼容性问题(如不支持 JSON.stringify 后的特殊字符);

  • 隐私模式:部分浏览器在隐私模式下会限制 Web 存储(如 Safari 隐私模式下 localStorage 读写会抛出异常),需添加异常捕获:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function safeSetItem(storage, key, value) {
    try {
    storage.setItem(key, value);
    return true;
    } catch (e) {
    console.error("存储失败:", e);
    alert("浏览器隐私模式下无法使用本地存储,请关闭隐私模式后重试!");
    return false;
    }
    }

    // 使用
    safeSetItem(localStorage, "theme", "dark");

Web 存储 vs Cookie:何时选择哪种方案?

Web 存储常与 Cookie 对比,二者均为客户端存储方案,但适用场景差异显著:

对比维度 Web 存储(localStorage/sessionStorage) Cookie
存储容量 约 5MB 约 4KB(容量极小,仅适合存储少量数据)
数据传输 不随 HTTP 请求发送到服务器 每次 HTTP 请求都会携带 Cookie(增加请求体积)
生命周期 localStorage 永久,sessionStorage 会话级 可设置过期时间(expires/max-age
服务器访问 仅客户端 JavaScript 可访问 客户端和服务器均可访问(服务器通过 Set-Cookie 头设置)
适用场景 客户端本地数据、离线缓存 身份认证(如 Session ID)、服务器端需要的少量数据
选择建议:
  • 若数据仅需客户端使用(如主题、临时表单),且容量较小(<5MB):选择 Web 存储;
  • 若数据需服务器端读取(如身份认证),或需设置过期时间:选择 Cookie;
  • 若数据容量较大(>4KB):选择 Web 存储或 IndexedDB。

总结

Web 存储是浏览器提供的轻量级客户端存储方案,通过 localStorage(永久共享)和 sessionStorage(临时私有)满足不同场景的需求,核心优势是 “无需服务器交互、操作简单、容量较大”。在实际开发中,需注意:

  1. 区分二者的生命周期和作用范围,避免混用;
  2. 处理非字符串数据时,需通过 JSON.stringify()/JSON.parse() 转换;
  3. 禁止存储敏感数据,注意同源策略和浏览器兼容性;
  4. 大量数据或异步操作需求,建议使用 IndexedDB 替代

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10