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.stringifyJSON.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,对应的值是一个对象。 在这个对象里,变量名为键,变量的值为值

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

相关推荐
沉默璇年4 分钟前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder10 分钟前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_8827275720 分钟前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
会发光的猪。1 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客1 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
猫爪笔记1 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
前端李易安2 小时前
Webpack 热更新(HMR)详解:原理与实现
前端·webpack·node.js
红绿鲤鱼2 小时前
React-自定义Hook与逻辑共享
前端·react.js·前端框架
周全全2 小时前
Spring Boot + Vue 基于 RSA 的用户身份认证加密机制实现
java·vue.js·spring boot·安全·php
Domain-zhuo2 小时前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式