学习关键语句:
pinia怎么用
写在前面
pinia 作为 vuex 的替代品好像变得不得不学习了,学起来一用发现 vuex 是什么麻烦的东西,我不认识
这篇文章一共包含的内容有:
- 安装 pinia
- 读取数据
- 修改数据
- 数据持久化
其中,修改数据只会演示比较常用的两种方式,数据持久化的方法来自满神的这篇文章
文章末尾会有此文章的使用文件链接
开始
安装 pinia
首先我们先创建一个空项目,这里我使用 vite 创建,各位用什么创建都可以
npm create vite
根据提示打开项目后,我们先将 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 ,不能保证后续版本兼容 注意
安装完成后,我们在 src 下新建文件夹叫 store,在 store 文件夹下新建文件 index.ts 和 仓库文件 test.ts
我们将在 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 中的数据
我们通过对比页面上的数据和 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>
我们加了三个按钮用来修改数据
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}`)
// 仓库中的数据发生改变时触发 $subscribe
store.$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 要清晰简洁上不少,如果你有什么疑问或者质疑,请在评论区告诉我
文件链接
这个项目我就放在这里了,点击下载就可以尝试了,不需要积分