前端常用本地存储方式

416 阅读6分钟

前端常用本地存储方式?

  • localStorage
  • sessionStorage
  • cookie

它们之间有什么区别?

特性localStoragesessionStoragecookie
持久性持久保存,需手动清除仅会话期间有效,标签页关闭即失效受 expires 或 max-age 控制
存储范围同源(协议、域名、端口一致)下的所有页面共享当前标签页独立存储同源下的所有页面共享
数据容量一般为 5MB一般为 5MB每个域名约 4KB
传输性能不随请求发送不随请求发送自动随 HTTP 请求发送到服务器
使用场景长期存储非敏感数据临时存储非敏感数据需与服务器通信的重要信息

选择建议

  • localStorage:存储长期需要的数据,比如主题设置、用户偏好。
  • sessionStorage:存储临时会话数据,比如分页、搜索条件。
  • cookie:存储需要在服务器端校验的信息,比如登录状态或会话标识。

Cookie 的用法

web端设置/读取 cookie

document.cookie 是浏览器提供的接口,可以直接操作 cookie。

// 设置 cookie
document.cookie = "key=value; expires=Fri, 19 Nov 2024 12:00:00 UTC; path=/; secure; samesite=strict";

// 多个属性解析
document.cookie = `
  username=JohnDoe;                     // 键值对
  expires=Fri, 19 Nov 2024 12:00:00 UTC; // 过期时间(GMT 格式)
  path=/;                                // 有效路径
  domain=.example.com;                   // 有效域名
  secure;                                // 仅通过 HTTPS 传输
  samesite=strict;                       // 防止 CSRF 攻击
`;

// 查看 cookie
console.log(document.cookie); // 输出当前页面的所有 cookie

// 修改 cookie
document.cookie = "key=newValue; path=/;";

// 删除 cookie
document.cookie = "key=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";

属性说明

  • expires:指定过期时间,格式为 GMT 时间。如果不设置,则为会话期 cookie,浏览器关闭即失效。
  • path:限定有效路径,默认为当前路径及其子路径。
  • domain:限定有效域名,默认为当前域名及其子域名。
  • secure:启用后仅在 HTTPS 环境下传输。
  • samesite:防范跨站请求伪造(CSRF),值可为:
  • strict:完全同站请求才发送。
  • lax:部分跨站请求可发送(如链接跳转)。
  • none:允许所有跨站请求(需配合 secure 使用)。

二级域名和一级域名的 Cookie 共享规则

  • Cookie 的 domain 属性必须显式设置为一级域名(如 colion.cn)。
  • 如果 domain 未设置,默认情况下,Cookie 仅适用于当前域名及其子路径,不能跨域共享。
// 一级域名设置 Cookie
document.cookie = "key=value; domain=colion.cn; path=/;";
// 此时,aaa.colion.cn 和 bbb.colion.cn 可以共享该 Cookie
  • 不可共享情况

如果 Cookie 设置为 domain=aaa.colion.cn,则只对 aaa.colion.cn 生效,其他子域(如 bbb.colion.cn 或 colion.cn)无法访问。

面试题

  • 问:Cookie 默认的作用域是什么?

:Cookie 默认仅适用于设置它的域名和路径范围内的资源,不能跨域名或路径访问。

  • 问:如何让二级域名和一级域名共享 Cookie?

:需要在设置 Cookie 时显式指定 domain 属性为一级域名(如 colion.cn)。

  • 问:domain 和 path 属性在 Cookie 中的作用分别是什么?

:domain 控制 Cookie 的适用域名范围,path 控制适用的路径范围

www.npmjs.com/package/js-…

js-cookie 是一个广泛使用的轻量级 JavaScript 库,用于浏览器中操作 Cookie。它以简单的 API 和强大的功能被大量前端项目采用,是操作 Cookie 的主流选择。

主要功能

  • 设置 Cookie

    • 可以轻松设置带有过期时间、路径、域名等属性的 Cookie。
    • 支持序列化复杂数据(如对象或数组)为字符串存储。
  • 获取 Cookie

    • 提供快捷方法获取指定名称的 Cookie
    • 自动解析存储的 JSON 数据
  • 删除 Cookie

    • 简化删除指定 Cookie 的操作

安装

pnpm add js-cookie

设置 Cookie

import Cookies from 'js-cookie';

// 设置 Cookie
// 设置简单值
Cookies.set('name', 'Colion');

// 设置带过期时间的值
Cookies.set('name', 'Colion', { expires: 7 }); // 7 天后过期

// 设置对象(会自动序列化为 JSON)
Cookies.set('user', { name: 'Colion', age: 25 });

获取 Cookie

console.log(Cookies.get('name')); // 输出:Colion

console.log(Cookies.get('user')); // 输出 JSON 字符串:{"name":"Colion","age":25}

删除 cookie

Cookies.remove('name');
// 删除一个 Cookie 时需要使用相同的 path 和 domain 设置,否则删除可能失败。
Cookies.remove('secureAuth', { path: '/', domain: 'colion.cn' });

设置路径和域名

Cookies.set('name', 'Colion', { path: '/', domain: 'colion.cn' });

设置过期时间 (expires)

expires 用于设置 Cookie 的有效期:

  • 可以是 天数,表示从设置时间起的有效天数。
  • 也可以是一个 Date 对象,表示具体的过期时间。
  • 如果不设置 expires,默认是会话 Cookie(关闭浏览器即失效)。
// 设置 7 天后过期
Cookies.set('theme', 'dark', { expires: 7 });

// 设置为指定的日期时间
const expireDate = new Date('2024-12-31T23:59:59');
Cookies.set('event', 'newyear', { expires: expireDate });

// 设置 Cookie 有效期为 7 天,作用于主域名和所有子域,在网站所有路径生效
Cookies.set('userSession', 'abc123', { 
  expires: 7,         // 7 天后过期
  path: '/',          // 在整个网站有效
  domain: 'colion.cn' // 主域及所有子域有效
});

注意

  • 未设置 expires 的 Cookie 是临时的,会在浏览器关闭时删除。
  • 设置 expires 后,Cookie 会存储在硬盘中,直到过期时间到达。

仅在 HTTPS 传输

Cookies.set('secureToken', 'secure123', { 
  expires: 30,      // 30 天后过期
  path: '/',        // 整个网站有效
  secure: true      // 仅在 HTTPS 下传输
});

防止跨站请求伪造(CSRF)攻击

  • 'Strict':完全禁止跨站发送 Cookie。
  • 'Lax':允许部分跨站请求发送(如 GET 请求)。
  • 'None':允许跨站发送,但需要设置 Secure。
Cookies.set('authToken', 'auth123', { 
  expires: 7,
  path: '/',
  secure: true,     // 与 SameSite=None 配合使用
  sameSite: 'Strict' // 禁止跨站发送 Cookie
});

适用场景

用户登录状态管理:存储 Token 或用户偏好。

页面功能记忆:记住用户选项(如语言、主题等)。

跨页面通信:在多页面应用中共享数据

序列化对象存储到 Cookie

假设你要将一个对象存储到 Cookie 中,可以使用 JSON.stringify() 来序列化该对象。

// 定义一个对象
const user = {
  name: "John",
  age: 30,
  email: "john@example.com"
};

// 序列化并存储到 Cookie
document.cookie = "user=" + encodeURIComponent(JSON.stringify(user)) + "; path=/;";

// 注意:使用 encodeURIComponent 确保值是有效的 Cookie 字符串
  • JSON.stringify(user) 将对象 user 转换为 JSON 字符串。
  • encodeURIComponent() 用来对字符串进行 URL 编码,防止一些特殊字符(如 = 或 ;)干扰 Cookie 的存储。

反序列化 Cookie 的值

读取存储的 Cookie 时,你需要将其从字符串转换回原始对象。这就是 反序列化

// 获取 Cookie
function getCookie(name) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop().split(';').shift();
  return null;
}

// 从 Cookie 中获取并反序列化对象
const userCookie = getCookie('user');
if (userCookie) {
  const userObject = JSON.parse(decodeURIComponent(userCookie));
  console.log(userObject);  // 输出对象 { name: "John", age: 30, email: "john@example.com" }
}
  • getCookie(name) 函数用来获取指定名称的 Cookie。
  • decodeURIComponent() 用于解码 Cookie 的值,确保它在存储和读取过程中没有丢失数据。
  • JSON.parse() 将 JSON 字符串解析回 JavaScript 对象。

完整的序列化和反序列化示例

// 序列化并存储对象到 Cookie
const user = {
  name: "Alice",
  age: 25,
  city: "New York"
};
document.cookie = "user=" + encodeURIComponent(JSON.stringify(user)) + "; path=/;";

// 反序列化读取 Cookie 中的对象
const userCookie = getCookie('user');
if (userCookie) {
  const userObject = JSON.parse(decodeURIComponent(userCookie));
  console.log(userObject);  // { name: "Alice", age: 25, city: "New York" }
}

// 获取 Cookie 的函数
function getCookie(name) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop().split(';').shift();
  return null;
}
  • 浏览器对每个 Cookie 大小有限制(一般为 4KB)。如果要存储的数据较大,可能需要考虑分割数据或使用其他存储机制(如 localStorage 或 sessionStorage)。
  • 在设置 Cookie 时,使用 encodeURIComponent() 对数据进行编码,防止特殊字符影响存储(如 = 和 ;)。
  • 如果没有设置 expires 或 max-age,Cookie 会在浏览器会话结束时自动过期。你可以使用 expires 来指定过期时间,或者使用 max-age 设置有效期(秒数)。