SSF0SSF0
首页
前端
  • Node
  • Go
  • Python
  • MySql
  • Bash
  • Git
  • Docker
  • VuePress
  • CI/CD
  • 服务器
  • 网站
  • 学习资料
  • 软件
  • 开源项目
Timeline
Github
标签
分类
首页
前端
  • Node
  • Go
  • Python
  • MySql
  • Bash
  • Git
  • Docker
  • VuePress
  • CI/CD
  • 服务器
  • 网站
  • 学习资料
  • 软件
  • 开源项目
Timeline
Github
标签
分类
  • HTML

    • html1
    • html2
  • CSS

    • Flex 布局常见问题与解决方案
  • JavaScript

    • 数据类型及引用问题
    • 处理 Blob 类型文件下载问题总结
    • localStorage 与 sessionStorage 区别
    • JavaScript 中的 script 标签问题详解
    • JavaScript 中的 this 指向问题详解
    • SessionStorage踩坑记录
    • 动态加载 JS 脚本方法对比
    • 浏览器页面关闭场景下的数据上报
    • HTTP流式接口详解与封装实践
    • JavaScript 中 this 绑定与解构:为什么 Pinia Store 可以解构,但 Class 实例方法不行?
  • es6

    • Promise
    • es6 模块导出方式全解析
    • reduce
    • forEach 中使用 async/await 的异步陷阱
  • Vue2

    • created VS mounted 发起异步请求
    • vue2-2
  • Vue3

    • Vite + Vue3 修改 element-plus 源码
    • Vue v-if 与 v-show
    • Vue3 ref 获取组件
    • Vue3 路由传参
    • 父子组件与组件里 Hooks 加载顺序
    • 第三方组件传入参数TS提示
    • Vue3 Props 在 Hooks 中的响应性处理
    • Vue Router 的两种历史模式及部署配置详解
    • 在Vue 3项目中顺利集成Tailwind CSS的完整指南
    • Vue Scoped CSS 深度解析
    • Vue 3 Teleport 组件完全指南:从原理到实战
    • Vant List 组件中双向绑定 loading 的注意事项
    • Vue 3 + Vite 中的路径别名与静态资源处理深度解析
    • 获取图片高度
    • 深入理解 Pinia:storeToRefs vs toRefs - 避开 TypeScript 类型推断的坑
  • webSocket

    • WebSocket 鉴权入门(实战版):握手票据 / 首帧鉴权 + 连接级 cid
  • Electron

    • 快速构建 electron + vue3 项目
  • TS

    • TS 泛型
    • 记录模板使用断言的问题
    • type 与 interface
  • WebPack

    • Webpack 介绍
  • Vite

    • Vite CLI 常见命令
    • vite 与 webpack 比较
    • Vite base 配置与 public 静态资源路径问题
  • 客户端数据库

    • IndexedDB 索引陷阱:字段重命名后索引返回旧数据
    • IndexedDB 事务陷阱与最佳实践:TransactionInactiveError 完全解析
  • UniApp

    • uni-app + Monorepo + 微信小程序热更新失效问题排查与结论总结
    • Monorepo + uni-app 开发中监听 / 热更新机制差异与解决方案
    • uni-app 运行与编译原理梳理
    • 为什么 uni-app 在 Monorepo 中必须做「环境区分」,而 Web 项目却不用?
  • 项目工程

    • 前端代码风格
    • Vue3 项目规范
    • npm 镜像问题
    • 包管理工具
    • 使用 engines 限制开发环境依赖
    • 打包与shell交互指定模式
    • Monorepo示例
    • PC 项目兼容 uni-app:基于 pnpm Monorepo 的工程化重构实践
    • Vue3 + Vite + pnpm Monorepo 迁移问题指南
    • 前端工程化:深入理解 npm 依赖管理机制
    • pnpm 修改依赖源码打包报错
    • 代码片段
  • 移动端

    • 浏览器跳转外部应用时请求状态码问题
  • 记录一下小程序
  • 控制浏览器正确保存网站账号密码的技巧
  • 信息泄露
  • 使用Gulp实现前端项目哈希化压缩打包
  • 前端缓存策略与文件哈希化的关联解析
  • 浏览器刷新方式与 Vue 生命周期、缓存行为解析
  • 浏览器消息铃声实现记录

SessionStorage 踩坑记录:它真的能"只设置一次"吗?

背景

在前端开发中,我们经常使用sessionStorage来存储一些临时数据。最近在一个 Vue 项目中,我遇到了一个关于sessionStorage的有趣问题,这让我对它的特性有了更深入的理解。

问题描述

在项目的路由守卫中,我们有这样一段代码:

router.beforeEach(async (to, _from, next) => {
  const userStore = useUserStore();

  if (!SessionStorageService.getData("PROJECT_URL")) {
    SessionStorageService.setData("PROJECT_URL", window.location.href);
  }

  // 其他代码...
  next();
});

最初,我没有加上if判断,直接使用:

router.beforeEach(async (to, _from, next) => {
  const userStore = useUserStore();

  SessionStorageService.setData("PROJECT_URL", window.location.href);

  // 其他代码...
  next();
});

发现每次页面跳转,PROJECT_URL的值都会更新为当前页面的 URL,这与我的预期不符。我原以为sessionStorage是"设置一次后就不能更改"的,但实际上并非如此。

误区澄清

误区:sessionStorage 设置一次后就不能更改

这是一个常见误解。实际上,sessionStorage可以被多次覆盖,只要你调用setItem(或封装的setData方法),就会覆盖同一个 key 的原有值。

例如:

sessionStorage.setItem("foo", "123");
console.log(sessionStorage.getItem("foo")); // 输出: 123

sessionStorage.setItem("foo", "456");
console.log(sessionStorage.getItem("foo")); // 输出: 456

sessionStorage 的特性

  1. 可多次更改:同一个 key 可以被多次设置,后面的值会覆盖前面的值

  2. 作用域限制:只在同一个标签页/窗口有效,关闭标签页后数据会清除

  3. 同源限制:只能被同源页面访问

  4. 容量较大:通常有 5MB 左右的存储空间

解决方案

如果你想实现"只设置一次"的效果,必须自己添加逻辑判断:

if (!SessionStorageService.getData("PROJECT_URL")) {
  SessionStorageService.setData("PROJECT_URL", window.location.href);
}

这样只有在sessionStorage中不存在该 key 时才会设置,实现了"只设置一次"的效果。

与其他存储方式对比

存储方式是否可多次更改生命周期作用域
sessionStorage✅标签页会话当前标签页
localStorage✅永久(除非手动清除)所有同源标签页
cookie✅可设置过期时间可配置(domain/path)

实现"只设置一次"的方法

如果你想封装一个"只设置一次"的方法,可以这样做:

function setOnce(key, value) {
  if (sessionStorage.getItem(key) === null) {
    sessionStorage.setItem(key, value);
    return true; // 设置成功
  }
  return false; // 已存在,未设置
}

经验教训

  1. 不要假设浏览器 API 的行为:在使用任何 API 前,最好先查阅文档,了解其真实行为

  2. 自己实现限制逻辑:如果需要特定的行为(如"只设置一次"),需要自己在代码层面实现

  3. 本地存储都是可覆盖的:sessionStorage、localStorage、cookie 等都可以被多次更改

结语

这次踩坑让我重新审视了前端存储的特性。记住,浏览器原生的存储机制都是可以多次更改的,没有"只写一次"的限制。如果你需要这样的功能,必须通过代码逻辑来实现。

最后更新时间:
贡献者: 何风顺
上一页
JavaScript 中的 this 指向问题详解
下一页
动态加载 JS 脚本方法对比