vue3:封装公共utils->pageState.ts公共组件,可控制存储和清理多sessionStorage

开始,我是用的是一个页面分别单独存储多个localstorage的值,但是后来发现我需要对每一个页面都存储不同的键值对,这就涉及到我现在的单个存储不行,要以页面进行区分key,value是每个页面的所有要存储的localstorage的值组成的对象,每个页面有一个对象,里面的值互不影响。

同时要考虑,采用localstorage还是sessionStorage

问:

javascript 复制代码
btnAction.vue:
<el-icon
        :style="dirLevelList.length > 1 ? 'cursor: pointer' : ''"
:size="16"
        color="#666"
title="返回上一级搜索页面"
        @click="returnRecordingLayer()"
        style="margin-right: 10px"
        v-if="shouldShowReturnIcon"
>
<svgIcon name="returnRecordingLayer" size="20px" />
</el-icon>
const returnRecordingLayer = () => {
      const  params = {
        userFileId: locationArr.value.userFileId,
        openDirFlag: locationArr.value.openDirFlag,
        searchScope: '0',
fileType: '0',
        keywordSearch: '',
      }
localStorage.setItem('returnRecordingLayer', 'true')
emit('updateSearchParams', params)
if (props.dirLevelList.length >= 1) {
router.push({
          path: route.path,
      query: {
            userFileId: JSON.parse(localStorage.getItem('firstSearchUserFileId')),
openDirFlag: 1,
          },
        })
      }
}
if (localStorage.getItem('isSearchResultList')) {
localStorage.setItem('isSearchResultList', 'false')
}

这是我的现有代码,我接下来的需求是:
我不希望一个一个单独存储firstSearchUserFileId,isSearchResultList,currentPath字段,而是形成一个对象去进行操作,以这个currentPath为依据,当前打开一个tab新的url标签就存储一个,以这个currentPath为基准,比如现在打开了三个tab页面那么就存储三个对应着三个url的对象,且当我切换tab的时候这些对象里面的数值不会相互影响,考虑一下用sessionStorage和是还是localstorage合适,告诉我为什么

回答:

javascript 复制代码
你提出的需求非常清晰,目标是将原本分散在 localStorage 中的多个状态字段(如 firstSearchUserFileId、isSearchResultList、currentPath 等)整合为以 currentPath 为键的对象结构进行管理,并支持多标签页(tab)场景下的独立状态隔离。

我们来一步步分析你的需求,并给出最佳实践方案。

✅ 一、核心需求总结
状态集中管理:不再单独存 firstSearchUserFileId、isSearchResultList 等字段,而是用一个对象统一管理。
按 currentPath(即当前路由路径)为键存储状态,实现不同页面/标签页的状态隔离。
支持多个 tab 同时打开不同路径页面时,各自保留独立状态,切换 tab 不互相干扰。
选择合适的存储方式:sessionStorage 还是 localStorage?

✅ 二、sessionStorage vs localStorage:选哪个?
特性	localStorage	sessionStorage
生命周期	永久保存(除非手动清除)	仅限当前会话,关闭浏览器标签页后清除
作用域	同源所有 tab 共享	每个 tab 独立(即使同 URL)
多 tab 隔离性	❌ 共享,会互相覆盖	✅ 每个 tab 有独立存储
是否适合你的场景	❌ 不适合多 tab 独立状态	✅ 强烈推荐
🟢 结论:使用 sessionStorage

因为你希望"每个打开的 tab 页面独立保存状态,切换 tab 时不互相影响",这正是 sessionStorage 的设计用途。

五、为什么用 sessionStorage 更合适?
原因	说明
多 tab 隔离	每个 tab 有自己的 sessionStorage,即使打开相同 URL,状态也不共享
自动清理	关闭 tab 后自动释放内存,无需手动清理
避免污染	不会影响其他标签页的状态,切换 tab 时不会"串数据"
会话级状态理想选择	正适合"页面级临时状态"这类需求
而 localStorage 是全局共享的,多个 tab 会互相覆盖,完全不适合多标签页独立状态场景。

✅ 为什么选 sessionStorage?
特性	localStorage	sessionStorage
是否跨标签页共享	✅ 是(所有同源 tab 共享)	❌ 否(每个 tab 独立)
关闭浏览器 tab 后是否清除	❌ 不清除	✅ 清除
是否支持多 tab 独立状态	❌ 会互相覆盖	✅ 完美支持
是否适合你当前场景	❌ 不适合	✅ 强烈推荐

✅ 六、额外建议
currentPath 是否足够唯一?
如果你有多个 tab 打开相同路径但不同参数(如 /file?userFileId=1 和 /file?userFileId=2),建议使用完整路径 + 查询参数作为 key:

const fullPath = route.path + '?' + JSON.stringify(route.query)
或者使用 route.fullPath(包含 query)
考虑性能:sessionStorage 是同步操作,但数据量小,无性能问题。
类型安全:可用 TypeScript 增强 pageState 类型。

✅ 七、最终总结
决策	结论
✅ 存储方式	sessionStorage(非 localStorage)
✅ 存储结构	以 currentPath(或 fullPath)为 key 的对象
✅ 封装方式	封装 pageState 工具类统一管理
✅ 多 tab 支持	✅ 完美支持,每个 tab 独立状态
✅ 推荐立即迁移:将所有 localStorage.getItem/setItem 关于页面状态的操作,替换为通过 


pageState.getState/setState 方法,基于 currentPath 统一管理。

这样你的代码会更清晰、可维护性更强,且完美支持多标签页场景。

问:

javascript 复制代码
// utils/pageState.js
export const pageState = {
  // 获取当前路径对应的状态
  get(path) {
    const key = `pageState_${path}`
    const item = sessionStorage.getItem(key)
    return item ? JSON.parse(item) : {
      firstSearchUserFileId: null,
      isSearchResultList: false,
      returnRecordingLayer: false
    }
  },

  // 设置当前路径的部分状态(合并)
  set(path, partialState) {
    const key = `pageState_${path}`
    const currentState = this.get(path)
    const newState = { ...currentState, ...partialState }
    sessionStorage.setItem(key, JSON.stringify(newState))
  },

  // 清除某个路径的状态
  clear(path) {
    const key = `pageState_${path}`
    sessionStorage.removeItem(key)
  }
}

这是我目前的代码,我希望实现:

我刷新浏览器chrome,希望清空之前的sessionStorage的记录,只保留当前所在路由的sessionStorage,且所在的也要重置sessionStorage

回答:

javascript 复制代码
你提出的问题非常典型,也很合理:

刷新浏览器时,希望清空所有 sessionStorage 记录,只保留当前路由的状态,并且该状态也要重置为初始值。

我们来一步步分析并给出最优解决方案。

❓ 问题本质
sessionStorage 是"会话级"存储,默认在页面刷新后仍然保留数据(因为它属于同一个会话)。
但你的需求是:刷新页面 = 重新开始 = 清空所有状态,重新初始化当前页状态。
所以不能依赖 sessionStorage 的默认行为。
✅ 目标
刷新页面时:

✅ 清空所有 sessionStorage 中的 pageState_xxx 数据;
✅ 仅保留当前 currentPath 对应的状态;
✅ 且这个当前状态也要重置为默认初始值(不是恢复旧值);
✅ 最佳解决方案:利用刷新检测 + 初始化拦截
✅ 核心思路
使用一个特殊的 sessionStorage 标志位(如 isPageRefreshed)来判断是否是刷新行为。
如果是刷新,则清空所有 pageState_* 数据,并重新初始化当前页面状态。

✅ Step 1:修改 pageState.js 工具类(增强初始化逻辑)

// utils/pageState.js

const STATE_KEY_PREFIX = 'pageState_'
const REFRESH_FLAG_KEY = '__refresh_check__'

export const pageState = {
  get(path) {
    const key = `${STATE_KEY_PREFIX}${path}`
    const item = sessionStorage.getItem(key)
    return item ? JSON.parse(item) : this.getDefaultState()
  },

  set(path, partialState) {
    const key = `${STATE_KEY_PREFIX}${path}`
    const currentState = this.get(path)
    const newState = { ...currentState, ...partialState }
    sessionStorage.setItem(key, JSON.stringify(newState))
  },

  clear(path) {
    const key = `${STATE_KEY_PREFIX}${path}`
    sessionStorage.removeItem(key)
  },

  // 清空所有 pageState_ 开头的状态
  clearAll() {
    Object.keys(sessionStorage).forEach(key => {
      if (key.startsWith(STATE_KEY_PREFIX)) {
        sessionStorage.removeItem(key)
      }
    })
  },

  getDefaultState() {
    return {
      firstSearchUserFileId: null,
      isSearchResultList: false,
      returnRecordingLayer: false
    }
  },

  // 初始化:在页面加载时调用
  initializeCurrentPage(path) {
    const flag = sessionStorage.getItem(REFRESH_FLAG_KEY)

    if (!flag) {
      // 第一次设置 flag,说明是刷新或新打开
      sessionStorage.setItem(REFRESH_FLAG_KEY, '1')

      // 清空所有 pageState_ 状态
      this.clearAll()

      // 设置当前页面为干净的初始状态
      this.set(path, this.getDefaultState())
    } else {
      // flag 存在,说明是正常跳转或激活,无需重置
      // 可以选择性地保留状态
    }

    // 确保当前页面至少有一个基础状态(兜底)
    if (!this.get(path)) {
      this.set(path, this.getDefaultState())
    }
  },

  // 页面卸载前清除 flag,确保下次刷新能再次触发初始化
  cleanupOnUnload() {
    // 注意:beforeunload 中不能读写 DOM 或异步操作
    sessionStorage.removeItem(REFRESH_FLAG_KEY)
  }
}

✅ 总结
需求	实现方式
刷新时清空所有状态	使用 __refresh_check__ 标志位检测刷新
仅保留当前路由状态	初始化时只设置当前路径状态
当前状态也要重置	initializeCurrentPage 中写入默认值
多 tab 支持	sessionStorage 天然支持
不影响正常跳转	flag 存在时不触发清空
✅ 你现在可以安全地刷新页面,所有状态都会"干净重启"。

这样你的状态管理就真正做到了:隔离、可重置、易维护 ✅