pinia最简单实现数据持久化的方法!有了这个插件,再也不用自己写localStorage了!pinia+pinia-plugin-persistedstate

前言

作者最近在学习pinia,作为vue官方推荐的状态管理库,pinia完美支持vue2和vue3。但是大部分的状态管理库都有一个痛点,无法原生支持数据持久化。

作者发现了一个pinia插件,可以完美解决这个痛点。只需三步,让你的pinia store实现数据持久化!

如果你已经了解pinia,可以跳转到这里

什么是pinia

pinia是一个全局状态管理工具,提供以下功能:

  • 完整的ts支持
  • 足够轻量,压缩有体积只有1kb左右
  • 去除了被认为是冗余的mutations,只有state、getters,actions
  • actions支持同步和异步
  • 代码扁平化,没有模块嵌套,只有store的概念,store之间可以自由使用,且每一个store都是独立的
  • 无需手动添加store,store一旦创建就会自动添加
  • 支持Vue2和vue3

pinia安装

sh 复制代码
npm install pinia -S

pinia引入

在main.ts中引入

ts 复制代码
import { createApp } from 'vue'
//从pinia中导入createPinia这个hook函数
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

const app = createApp(App)
//调用createPinia函数,获取pinia实例
const pinia = createPinia()

//将pinia实例作为vue插件,在app里注册
app.use(pinia)
app.use(router)

app.mount('#app')

pinia使用

创建pinia store

基于vue约束,首先让我们在/src/目录下建立stores文件夹 /src/sotres 然后在sotres文件夹里创建pinia store

然后在该文件里编写我们的pinia store,我们这里使用组合式API的写法,如果你更熟悉state、getter和actions的声明式写法,可以去官网查看。

js 复制代码
import { defineStore } from 'pinia'

export const useUserInfoStore = defineStore('user', () => {
  const userName = "李卢"
  const age = 20
  return {
    userName,
    age
  }
})

首先从pinia里导入definestore()函数,这个函数接收两个参数:

  • StoreId:字符串,用于唯一标识store
  • 回调函数:在这个回调函数里面编写代码,最后return一个对象,这个对象里的属性就是pinia仓库里的状态。这个状态可以被其他组件使用和修改。

请注意,只有回调函数返回的对象里的值,才能被其他组件访问

defineStore()函数会返回一个hook函数,我们用一个use开头的变量接收。使用use开头是vue写法约束,让别人一眼就知道,你这个是一个pinia store的hook函数。 最后我们将这个use开头的变量export,这样就可以在其他vue组件中导入使用

使用pinia store

我们首先从刚才编写的userInfo.ts文件中,导入pinia store的hook函数

js 复制代码
import { useUserInfoStore } from "./stores/userInfo"

然后调用hook函数,获取该pinia store实例

js 复制代码
const userInfoStore = useUserInfoStore()

现在我们就可以通过userInfoStore访问到定义的状态了

js 复制代码
console.log(userInfoStore.userName)
console.log(userInfoStore.age)
//"李卢"
//20

最后附上完整代码:

vue 复制代码
<template>
    <div>
        <div>{{ userInfoStore.userName }}</div>
        <div>{{ userInfoStore.age }}</div>
    </div>
</template>

<script setup lang="ts">
import { useUserInfoStore } from "./stores/userInfo";
const userInfoStore = useUserInfoStore();
</script>

最终呈现效果

我们也可以在其他组件中导入,实现组件之间的状态共享

通过插件实现pinia数据持久化

pinia和vuex都有一个通病,没有自带的持久化储存,页面刷新状态丢失。 可以通过pinia插件将数据持久化,pinia-plugin-persistedstate这个插件旧可以实现pinia数据持久化

什么是pinia-plugin-persistedstate

persistedstate 丰富的功能可以使 Pinia Store 的持久化更易配置:

  • 与 vuex-persistedstate 相似的 API
  • 所有 Store 均可单独配置
  • 自定义 storage 和数据序列化
  • 恢复持久化数据前后的 hook
  • 每个 Store 具有丰富的配置
  • 兼容 Vue 2 和 3
  • 无任何外部依赖

pinia-plugin-persistedstate安装

安装

sh 复制代码
npm i pinia-plugin-persistedstate

注册pinia插件

在main.ts中添加

ts 复制代码
import { createApp } from 'vue'
import { createPinia } from 'pinia'
//导入持久化插件
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

import App from './App.vue'
import router from './router'

const app = createApp(App)
const pinia = createPinia()

app.use(pinia)
app.use(router)
//pinia注册持久化插件
pinia.use(piniaPluginPersistedstate)

app.mount('#app')

请注意!如果你是通过npm create vue@latest创建的vue项目,且创建时添加了pinia 那么您的main.ts配置为:

js 复制代码
import './assets/main.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

const app = createApp(App)

//这里注册的方式不一样,请注意
app.use(createPinia())
app.use(router)

app.mount('#app')

store启用数据持久化

创建Store时,向defineStore()传入第三个参数,即配置对象,将persist选项设置为true,同时将需要储存到localStorage里的数据用ref包裹

ts 复制代码
import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useUserInfoStore = defineStore('userInfo', () => {
  const userName = ref("李卢")
  const age = ref(20)
  return {
    userName,
    age
  }
},{
  persist: true
})

这里作者踩坑了,如果不需要数据持久化的话,store里的数据无需ref()包裹,就可以获得响应性。 但是如果需要数据持久化的话,一定要将数据用ref()包裹。如果没包裹的话,持久化插件会失效。就是这一点困扰了作者很多天

插件实现数据持久化的方式

该插件的默认配置如下:

  • 使用 localStorage 进行存储
  • store.$id 作为 storage 默认的 key
  • 使用 JSON.stringify 和JSON.parse进行序列化/反序列化
  • 整个 state 默认将被持久化

最终效果

最后跟着作者一起来看看持久化效果吧

vue 复制代码
<template>
    <div>
        <input type="text" v-model="userInfoStore.userName">
        <input type="text" v-model="userInfoStore.age">

        <div>{{ userInfoStore.userName }}</div>
        <div>{{ userInfoStore.age }}</div>
    </div>
</template>

<script setup lang="ts">
import { useUserInfoStore } from "./stores/userInfo";
const userInfoStore = useUserInfoStore();
</script>

初始化时,localStorage里没有存入数据 然后我们修改userName为李大卢,修改age 为21 可以看到,在localStorage中,pinia store的id作为了Key,对应的值是一个对象。 在这个对象里,变量名为键,变量的值为值

刷新界面后,我们的修改仍然还在。到这里我们就实现了数据通过插件非常简单的实现了数据持久化

相关推荐
Csvn2 小时前
性能监控
前端
Csvn2 小时前
构建工具
前端
FRing033 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
Java小卷3 小时前
JuanForm vs FormCreate!Vue3 表单引擎联动配置 PK!
vue.js·低代码
kyriewen5 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
IT_陈寒5 小时前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端
工控丫丫6 小时前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库
jerrywus6 小时前
我用 GPT-6.1-sol 做了台会讲解的 3D 售货机:60 罐饮料,一口没喝上
前端·agent·claude
孟陬7 小时前
Foobar 技术周刊#159:当看不懂代码时,如何高效排障调试。脏页陷阱:一条只读查询,写入数 TB 数据。推测解码:大模型加速利器
前端·人工智能·后端
Zhao-Jichao7 小时前
AI Prompting for Everyone 课程笔记 - P17 图像生成 Imaging Generation
前端