查看: 121|回复: 0

Pinia刷新丢状态:localStorage与持久化插件

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
在 Vue3 项目里使用 Pinia 管理用户状态时,常见现象是:调用过 setUsername 后当前页面显示正常,但浏览器刷新后 username 又变空。原因在原文现象中已经明确:Pinia 状态默认只保存在内存,页面刷新会重新初始化 Store;Store 里虽然写了 localStorage.setItem 做保存,但初始化时没有从 localStorage 读取恢复数据。

问题定位

原有逻辑只完成了“写入”这一半:setUsername 修改 username 并写入 localStorage,clearUser 清空 username 并移除 localStorage;但 username 初始值仍是 ref('')。因此刷新时 Store 重新创建,值回到空字符串,已经保存到 localStorage 的数据没有被读回。

方案一:手动补全初始化读取

如果当前只有 username 一个字段需要持久化,不需要安装插件,直接修改 stores/user.ts,把初始值改为从 localStorage 读取,没有值时回退为空字符串:
  1. import { defineStore } from 'pinia'
  2. import { ref } from 'vue'
  3. export const useUserStore = defineStore('user', () => {
  4.   // 初始化时从 localStorage 读取,没有则默认空字符串
  5.   const username = ref(localStorage.getItem('username') || '')
  6.   function setUsername(name: string) {
  7.     username.value = name
  8.     localStorage.setItem('username', name)
  9.   }
  10.   function clearUser() {
  11.     username.value = ''
  12.     localStorage.removeItem('username')
  13.   }
  14.   return { username, setUsername, clearUser }
  15. })
复制代码

这段改动的核心只有初始化表达式:ref('') 改为 ref(localStorage.getItem('username') || '')。刷新后重新初始化 Store 时,会先从 localStorage 读取之前保存的用户名;setUsername 和 clearUser 仍分别负责写入和删除。适用场景是持久化字段很少、逻辑简单,手动维护读写成本低。

方案二:使用 pinia-plugin-persistedstate 插件

如果后续还要持久化 token、权限等更多状态,逐个字段手写 localStorage 容易遗漏。原文推荐使用 pinia-plugin-persistedstate,由插件自动处理存取。

第一步,安装插件:
  1. npm install pinia-plugin-persistedstate
复制代码

第二步,在 main.ts 中创建 Pinia 实例并注册插件:
  1. import { createApp } from "vue";
  2. import { createPinia } from "pinia";
  3. import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
  4. import App from "./App.vue";
  5. import router from "./router/index.ts";
  6. const app = createApp(App);
  7. const pinia = createPinia();
  8. pinia.use(piniaPluginPersistedstate); // 注册持久化插件
  9. app.use(pinia);
  10. app.use(router);
  11. app.mount("#app");
复制代码

第三步,在 Store 的第二个参数中开启 persist:
  1. import { defineStore } from 'pinia'
  2. import { ref } from 'vue'
  3. export const useUserStore = defineStore('user', () => {
  4.   const username = ref('')
  5.   function setUsername(name: string) {
  6.     username.value = name
  7.   }
  8.   function clearUser() {
  9.     username.value = ''
  10.   }
  11.   return { username, setUsername, clearUser }
  12. }, {
  13.   persist: true // 开启持久化,自动存入 localStorage
  14. })
复制代码

开启后,username 变化时插件会自动写入 localStorage,页面刷新时自动读取恢复,Store 内不再需要手写 localStorage.setItem 和 localStorage.getItem。与方案一相比,方案二把持久化逻辑交给插件统一处理,更适合状态字段会持续增加的项目。

选择建议

当前只有 username 一个字段时,方案一只需改一行初始化代码,改动最小;如果后续还有 token、权限等更多状态需要持久化,方案二可以减少重复的手动读写代码,避免新增字段时漏掉初始化读取。两种方案都围绕同一个根因:Pinia 状态在内存中,刷新会重建,必须显式从 localStorage 恢复,或由持久化插件完成自动恢复。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-24 16:28 , Processed in 0.029621 second(s), 29 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部