> 文章列表 > vue中的pinia使用和持久化 - 粘贴即用

vue中的pinia使用和持久化 - 粘贴即用

vue中的pinia使用和持久化 - 粘贴即用

学习关键语句:
pinia怎么用

写在前面

pinia 作为 vuex 的替代品好像变得不得不学习了,学起来一用发现 vuex 是什么麻烦的东西,我不认识

这篇文章一共包含的内容有:

  • 安装 pinia
  • 读取数据
  • 修改数据
  • 数据持久化

其中,修改数据只会演示比较常用的两种方式,数据持久化的方法来自满神的这篇文章

文章末尾会有此文章的使用文件链接

开始

安装 pinia

首先我们先创建一个空项目,这里我使用 vite 创建,各位用什么创建都可以

npm create vite

vue中的pinia使用和持久化 - 粘贴即用
根据提示打开项目后,我们先将 App.vue 页面清空

App.vue

<template><div>123</div>
</template>
<script setup lang='ts'>
</script>
<style scoped>
</style>

接下来我们来安装 pinia

npm i pinia

写这篇文章时间的时候 pinia 的版本为 2.0.34 ,不能保证后续版本兼容 注意
vue中的pinia使用和持久化 - 粘贴即用

安装完成后,我们在 src 下新建文件夹叫 store,在 store 文件夹下新建文件 index.ts 和 仓库文件 test.ts

vue中的pinia使用和持久化 - 粘贴即用

我们将在 index.ts 文件中创建 pinia 实例

index.ts

import { createPinia } from 'pinia'export const store = createPinia()

我们在 main.ts 中去引入并使用,这里弄得这么麻烦的原因是接下来还要进行持久化操作

main.ts
第 4 行和第 6 行

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { store } from './store'createApp(App).use(store).mount('#app')

接下来我们来制作我们的第一个仓库,喔我早就创建好文件了,这个仓库就叫 test 好了

注意 !在这里我遇到一个问题,导致仓库中的响应式对象只能通过 ref 设置而不能使用 reactive ,使用 reactive 声明的对象在持久化后数据会复原,但我找不到原因,希望有大佬能积极在评论区指点我

我们准备一些数据

test.ts

import { ref } from 'vue'
import { defineStore } from 'pinia'// defineStore 第一个参数是仓库名,第二个仓库类似于 setup
export const useTestStore = defineStore('test', () => {const num = ref<number>(0)const name = ref<string>('shaoyahu')const user = ref<{ name: string, age: number }>({name: '名字叫:',age: 18})const hobby = ref<string[]>(['sing', 'dance'])// 修改值的第一种方式 使用仓库的方法function addnum() {num.value++}function addhobby() {hobby.value.push('rap')}return {num,name,user,hobby,addnum,addhobby}
})

好了,到目前为止,我们的仓库已经准备好了,现在我们去读取数据吧

读取数据

我们将在刚才清空的 App.vue 页面中读取数据

App.vue

<template><div>test.num:{{ test.num }}<hr>test.name:{{ test.name }}<hr>test.user:{{ test.user }}<hr>test.hobby:{{ test.hobby }}<hr><button @click="test.addnum">num加一</button><button @click="test.addhobby">hobby加一个</button></div>
</template><script setup lang='ts'>
import { useTestStore } from './store/test'const test = useTestStore()
</script><style scoped></style>

我们打开浏览器的 vue 工具,里面可以看到 pinia 中的数据
vue中的pinia使用和持久化 - 粘贴即用
我们通过对比页面上的数据和 pinia 中的数据,就知道数据已经被我们正常读取到了,接下来我们来试试修改数据

修改数据

修改数据常用的有两种方式,一种是使用仓库中的修改数据的方法,一种是我们直接修改仓库中的数据

使用方法

直接使用仓库中的方法,在上面的文件中,我们点击那两个按钮就可以修改数据了,我们来看一看

vue中的pinia使用和持久化 - 粘贴即用

创建函数修改

我们自己创建函数来修改仓库中的数据

App.vue

<template><div>test.num:{{ test.num }}<hr>test.name:{{ test.name }}<hr>test.user:{{ test.user }}<hr>test.hobby:{{ test.hobby }}<hr><button @click="test.addnum">num加一</button><button @click="test.addhobby">hobby加一个</button><button @click="editname">当场改名</button><button @click="change">给user加个名字</button><button @click="delhobby">删除一个hobby</button></div>
</template><script setup lang='ts'>
import { useTestStore } from './store/test'const test = useTestStore()
const editname = () => {test.name = '邵雅虎'
}
const change = () => {test.user.name += test.name
}
const delhobby = () => {test.hobby.pop()
}
</script><style scoped></style>

我们加了三个按钮用来修改数据
vue中的pinia使用和持久化 - 粘贴即用

ok 这样我们修改数据也获得大成功,不过有一个问题,那就是这样修改的数据在浏览器刷新后就会恢复,所以我们接下来做数据持久化

数据持久化

想想为什么可以做到数据持久化,前端能把数据放哪呢,不就是放在浏览器里嘛,我们将数据存进浏览器的 localStorage 中

我们先在 src 目录下新建文件夹 utils ,并在文件夹下新建文件 storage.ts,我们封装两个方法来存取storage数据

storage.ts

//存缓存中
export const setStorage = (key: string, value: any) => {localStorage.setItem(key, JSON.stringify(value))
}
//缓存中读取
export const getStorage = (key: string) => {return (localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key) as string) : {})
}

接下来我们回到 store 下的 index.ts 文件中,进行数据持久化修改

index.ts

import { toRaw } from 'vue'
import { createPinia, type PiniaPluginContext } from 'pinia'
import { getStorage, setStorage } from '../utils/storage'export const store = createPinia()// 定义一个默认的保存在 localstroge 中的名字
const __piniaKey__: string = 'piniaDefault'
// 制作一个 pinia 插件
const piniaPlugin = (options?: any) => {return (context: PiniaPluginContext) => {const { store } = context// 读取上回存到的数据const data = getStorage(`${options?.key ?? __piniaKey__}-${store.$id}`)// 仓库中的数据发生改变时触发 $subscribestore.$subscribe(() => {let o = toRaw(store.$state)let obj: any = {}for (const key in o) {obj[key] = o[key].value}// 存入最新的数据setStorage(`${options?.key ?? __piniaKey__}-${store.$id}`, obj)})return {...data}}
}
// 使用插件,不给 key 时则使用默认名字
store.use(piniaPlugin({key: 'pinia'
}))

大致的逻辑就是每次数据更新后将新数据存入 localstroge ,每次刷新页面时都会从 localstroge 中读取数据

注意 ! 这里面有一个问题我没解决,就是在仓库中使用 reactive 定义的响应式对象的数据无法持久化,我试了好久,没有改出来,求求大佬捞一捞

结束

这样子一来,pinia 的使用也就非常清楚了,目前来看,确实要比 vuex 要清晰简洁上不少,如果你有什么疑问或者质疑,请在评论区告诉我

文件链接

这个项目我就放在这里了,点击下载就可以尝试了,不需要积分