2.1.7 network-浏览器-前端浏览器数据存储

前端浏览器数据存储

在前端开发中,浏览器存储是保存数据的重要方式之一。常见的浏览器存储方案有cookie、localStorage、sessionStorage、indexDB等。选择合适的存储方案对应用性能和用户体验有重要影响。

cookie内容请参考Cookie专题

2. sessionStorage

sessionStorage为每一个给定的源(given origin)维持一个独立的存储区域,该存储区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和恢复)。

js 复制代码
// 保存数据到 sessionStorage
sessionStorage.setItem('key', 'value');

// 从 sessionStorage 获取数据
var data = sessionStorage.getItem('key');

// 从 sessionStorage 删除保存的数据
sessionStorage.removeItem('key');

// 从 sessionStorage 删除所有保存的数据
sessionStorage.clear();

sessionStorage在创建时便已确定了生命周期,即在当前标签页关闭时数据会被清除。

2.1 应用场景

  • 临时表单数据保存(防止页面刷新丢失)
  • 页面间临时数据传递
  • 多步骤表单的状态管理
  • 临时购物车信息

3. localStorage

localStorage 同样为每一个给定的源(given origin)维持一个独立的存储区域,但其生命周期不会因为标签页的关闭而清除,除非主动清除。

js 复制代码
// 保存数据到 localStorage
localStorage.setItem('key', 'value');

// 从 localStorage 获取数据
var data = localStorage.getItem('key');

// 从 localStorage 删除保存的数据
localStorage.removeItem('key');

// 从 localStorage 删除所有保存的数据
localStorage.clear();

3.1 数据存储优化

js 复制代码
// 对于复杂对象,使用JSON序列化
const userInfo = {
  name: '张三',
  age: 25,
  preferences: ['reading', 'coding']
};

// 存储
localStorage.setItem('userInfo', JSON.stringify(userInfo));

// 读取
const storedUserInfo = JSON.parse(localStorage.getItem('userInfo') || '{}');

3.2 存储空间检测

js 复制代码
// 检查localStorage是否可用
function isLocalStorageAvailable() {
  try {
    const test = '__test__';
    localStorage.setItem(test, test);
    localStorage.removeItem(test);
    return true;
  } catch(e) {
    return false;
  }
}

// 检查存储空间
function getLocalStorageSize() {
  let size = 0;
  for(let key in localStorage) {
    if(localStorage.hasOwnProperty(key)) {
      size += localStorage[key].length;
    }
  }
  return size;
}

3.3 数据过期处理

js 复制代码
// 带过期时间的localStorage封装
class StorageWithExpiration {
  static set(key, value, ttl) {
    const data = {
      value: value,
      expiry: new Date().getTime() + ttl,
    };
    localStorage.setItem(key, JSON.stringify(data));
  }
  
  static get(key) {
    const item = localStorage.getItem(key);
    if (!item) {
      return null;
    }
    const data = JSON.parse(item);
    if (new Date().getTime() > data.expiry) {
      localStorage.removeItem(key);
      return null;
    }
    return data.value;
  }
}

// 使用示例
StorageWithExpiration.set('tempData', 'temporary value', 5000); // 5秒过期
const value = StorageWithExpiration.get('tempData');

3.4 应用场景

  • 用户偏好设置(主题、语言等)
  • 长期缓存的数据(如城市列表、用户信息)
  • 离线应用的数据存储
  • 购物车持久化

4. 浏览器存储方案对比

特性 cookie localStorage sessionStorage indexDB
生命周期 一般由服务器生成,可以设置过期时间 除非被清理,否则一直存在 页面会话期间可用(标签页关闭即清除) 除非被清理,否则一直存在
存储大小 4KB 5MB 5MB 无限
与服务端通信 每次都会携带在header中,对于请求性能有影响 仅在客户端存储,不与服务端通信 仅在客户端存储,不与服务端通信 仅在客户端存储,不与服务端通信
存储方式 只能存储字符串类型数据 只能存储字符串类型数据 只能存储字符串类型数据 可以存储任何类型数据
同步/异步 同步 同步 同步 异步

5. sessionStorage数据共享机制

html 复制代码
<!-- 使用一个新标签页打开自身,并设置一个 sessionStorage -->
<a href="index.html" target="_blank" onclick="sessionStorage.setItem('name', 'liam')">open myself</a>
  1. 在浏览器中打开这个 index.html,我们称之为标签页 A。注意:需要用 http 协议打开!例如 http://localhost/index.html
  2. 点击页面上的链接,此时会弹出来标签页 B。
  3. 在标签页 B 中打开控制台并执行 sessionStorage.getItem('j')
  4. 控制台输出's',这说明标签页 A 和 B 共享了 sessionStorage 中的数据
  5. 接下来,先关闭这两个标签页,然后再打开一个标签页 C,再读取一下 j 的值,得到的是 null

但是如果进行如下操作发现表现与预期不符合:

  1. 在浏览器中打开这个 index.html,我们称之为标签页 A。注意:需要用 http 协议打开!例如 http://localhost/index.html
  2. 点击页面上的链接,此时会弹出来标签页 B。
  3. 在标签页 B 中打开控制台并执行 sessionStorage.getItem('j'),得到 's'
  4. 新建一个新标签页 D,然后在地址栏内输入 http://localhost/index.html 打开同样的页面, 然后执行 sessionStorage.getItem('j')
  5. 按照我的预期,标签页 D 得到的应该还是 's',毕竟我认为 sessionStorage 的数据是在同一网站的多个标签页之间共享的。但是我错了,得到的结果是 null

标签页 B 和标签页 D 之间唯一的不同就是它们被打开的方式:标签页 B 是通过在标签页 A 中点击链接打开的,但标签页 D 是在浏览器地址栏输入地址打开的

通过点击链接(或者用了 window.open)打开的新标签页之间是属于同一个 session 的(因为她们共用了同一个浏览器的进程),但新开一个标签页总是会初始化一个新的 session,即使网站是一样的,它们也不属于同一个 session

localStorage - 只要是同源,不同 Tab 之间均可读写,相互影响。 sessionStorage - 前提还是同源, 同一 Tab 在新标签或窗口打开一个页面时会复制顶级浏览会话的上下文作为新会话的上下文,复制之后读写操作独立,"互不影响"。 不同 Tab 之间,读写操作独立,"互不影响"。 上面打引号原因是,<a target="_blank"></a> 和 window.open() 两种方式创建新 Tab 的初始缓存不一样。前者是全新的一个 sessionStorage 对象,且初始值为空。后者则基于原页面的 sessionStorage 拷贝一份,并作为新 Tab 的初始缓存值。 Cookie - 只要 Domain 和 Path 一致情况下,不同 Tab 之间即可相互读取。Cookie 最宽松的情况是同站即可,就是说 Domain 设为二级域名、Path 设为 /。

sessionStorage 的数据会在同一网站的多个标签页之间共享吗?这取决于标签页如何打开

6. 安全注意事项

  • 敏感信息不应存储在客户端存储中
  • 对于用户身份凭证,应使用HttpOnly cookie
  • 注意存储数据的隐私合规性
  • 定期清理不需要的存储数据
相关推荐
洋葱头_2 小时前
vue3项目不支持低版本的android,如何做兼容
前端·vue.js
前端小书生2 小时前
React 组件渲染
前端·react.js
sjd_积跬步至千里2 小时前
CSS实现文字横向无限滚动效果
前端
维他AD钙2 小时前
前端基础避坑:3 个实用知识点的简单用法
前端
journs2 小时前
micro-app微前端styled-components CSSOM模式 应用切换样式丢失问题
前端
呼啦啦小魔仙2 小时前
elpis项目DSL设计分享
前端
李李记2 小时前
别让 “断字” 毁了 Canvas 界面!splitByGrapheme 轻松搞定非拉丁文本换行
前端·canvas
来金德瑞2 小时前
快速掌握 ProseMirror 的核心概念
前端
ygria2 小时前
样式工程化:如何实现Design System
前端·前端框架·前端工程化