nuxt3+pinia 实现数据持久化
在 nuxt 3 项目中,我们使用 pinia 存储数据时,如果刷新页面的话数据就消失了,所以我们需要做数据持久化。
配置 pinia
安装相关的依赖:
pnpm add pinia @pinia/nuxt
然后在 nuxt.config.ts 中进行修改位置:
export default defineNuxtConfig({
+ modules: [
+ '@pinia/nuxt'
+ ]
})
在项目中使用:
import {defineStore} from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: '',
token:'',
}),
getters: {},
actions: {
async userLogin(data: any) {
this.loginLoading = true
}
}
})
使用 pinia 插件实现持久化
项目中使用的比较多的就是实用插件来实现持久化,在 pinia 中有个下载量比较多的插件 pinia-plugin-persistedstate
,插件官网为:pinia-plugin-persistedstate
安装插件:
pnpm add @pinia-plugin-persistedstate/nuxt
配置下 nuxt.config.ts:
modules: ['@unocss/nuxt', '@pinia/nuxt', '@element-plus/nuxt','@pinia-plugin-persistedstate/nuxt'],
piniaPersistedstate: {
storage: 'localStorage',
},
在需要持久化的 store 里面添加一行:
export const useUserStore = defineStore('user', {
state: () => ({
loginLoading: false
}),
getters: {},
actions: {},
persist: true
})
设置为 true,表示这个 store 要进行持久化处理。
使用 vueuse
vueuse
中有个 storage
相关的 hook,我们可以使用 hook 来保存 store
。刷新的时候从 storage
中读取数据,就达到了数据保存的效果。
我们先安装依赖:
pnpm i -D @vueuse/nuxt @vueuse/core
然后配置 nuxt.config.ts 文件:
modules: ['@vueuse/nuxt']
然后我们就可以在项目中使用了,要使用的 useStorage
方法所在官网位置为:useStorage
我们需要修改原来的 store 使用方式:
import { defineStore } from 'pinia'
import { useStorage } from '@vueuse/core'
export const useUserStore = defineStore('user', () => {
const state = useStorage('text-demo', {
name: 'aaa',
count: 0
})
const setState = () => {
console.log(state)
state.value.count++
}
return {
state,
setState
}
})
在页面中使用:
<template>
<div>
<client-only>
<div>
{{ userStore.state.count }}
</div>
</client-only>
<div>
<button @click="userStore.setState">点击count</button>
</div>
</div>
</template>
<script setup lang="ts">
const userStore = useUserStore()
</script>
我们可以发现这样是可以使用的,但是当页面刷新的时候,我们会发现 storage 里面存储的 count 已经变为了 0
具体的原因我们可以去 官网 上查找为啥会报错,因为在 SSR 环境下使用 composables
需要额外处理
当我们在 SSR 下使用 useStorage
的时候,需要考虑 hydrate
阶段的处理,state
的值应该是从浏览器读取,而不需要再 hydrate
阶段进行激活,所以我们需要对这些字段跳过处理:
import { defineStore } from 'pinia'
import { useStorage } from '@vueuse/core'
import { skipHydrate } from 'pinia'
export const useUserStore = defineStore('user', () => {
const state = useStorage('text-demo', {
name: 'aaa',
count: 0
})
const setState = () => {
console.log(state)
state.value.count++
}
return {
state: skipHydrate(state),
setState
}
})
使用 skipHydrate
方法,来进行标记 state
属性不能被激活,需要到浏览器中读取数值,这样处理后再页面刷新的时候也能保持数据的内容了
使用自定义插件
除了以上两种方案以外,如果想用其他的方式来实现的话可以使用 pinia
插件来实现。
在 pinia插件文档中介绍了 nuxt
环境中如何使用 pinia
插件了:
// plugins/myPiniaPlugin.ts
import {PiniaPluginContext} from 'pinia'
function MyPiniaPlugin({store}:PiniaPluginContext) {
store.userInfo = localStorage.get('userInfo')
store.token = localStorage.get('token')
}
export default defineNuxtPlugin(({$pinia}) => {
$pinia.use(MyPiniaPlugin)
})
这样我们在页面加载的时候就可以从缓存中获取到值。