Nuxt3 Pinia使用VueUse useStorage刷新后加载默认值无法持久化
问题根因
持久化失效是两个写法问题叠加导致的:
- 冗余
ref嵌套:useStorage本身返回的就是自带LocalStorage双向绑定的响应式Ref对象,额外在外层包一层ref(),相当于把真正和存储绑定的ref塞到了外层ref的.value下。实际状态读写操作的都是外层普通ref,和LocalStorage的绑定链路直接断开,页面刷新初始化时会把传入的默认值挂到外层ref,覆盖从本地存储读到的内容。 - SSR兼容缺失:vitesse-nuxt3是Nuxt3 SSR模板,服务端渲染阶段不存在浏览器的
window、localStorage对象,useStorage在服务端执行时只能返回默认初始值。如果不做客户端侧的初始化判断,客户端水合阶段会直接复用服务端返回的初始状态,不会主动读取本地已经存好的值。
另外你贴的组件代码里,input的v-model="value"没有对应定义的响应式变量,测试时会导致修改无法同步到store。
修复步骤
- 修改Pinia Store代码,去掉多余的ref包裹,同时加客户端环境判断处理SSR兼容:
import { acceptHMRUpdate, defineStore } from 'pinia' import { useStorage } from '@vueuse/core' export const useTestStore = defineStore('test', () => { // 服务端返回普通ref默认值,客户端初始化时直接用useStorage绑定本地存储 const test = process.client ? useStorage('test', { initials: 'It is initials', }) : ref({ initials: 'It is initials' }) return { test, } }) if (import.meta.hot) import.meta.hot.accept(acceptHMRUpdate(useTestStore, import.meta.hot))
- 修改组件代码,把input的v-model绑定到store对应的字段上,确保修改能同步到存储:
<script setup lang="ts"> const { test } = useTestStore() </script> <template> <div> <pre>{{ test }}</pre> <hr> <input id="slug" v-model="test.initials" type="text" > </div> </template>
额外说明
- 改完后修改输入框内容,LocalStorage里的对应值会实时更新,刷新页面后会优先读取本地存储的值,不会再重置为默认初始值。
- 如果需要自定义存储方式、序列化规则,直接给
useStorage传对应配置参数即可,不需要额外包裹ref或者做其他响应式处理。
内容的提问来源于stack exchange,提问作者Zach Inglis
相关产品推荐
相关产品推荐

