Vue Pinia 是一个专为Vue设计的状态管理库。它提供了一种简单、直观且强大的方式来管理Vue应用中的状态。
Store | 用于保存和管理应用的状态。每个store都是一个独立的状态,包含自己的State、Getters和Actions。 |
State | 状态,类似Vue的data。用于存储store的当前状态。 |
Getters | 类似Vue的计算属性。 |
Actions | 类似Vue的methods。 |
表 Pinia 的核心概念
// store/user.ts 选项式
import {defineStore} from "pinia";
export const useUserStore = defineStore('user',{
state() {
return {name: '',address: ''}
},
getters: {
userStr: (state) => state.name + "/" + state.address
},
actions: {
setInfo(name: string, address: string) {
this.name = name
this.address = address
}
}
})
// store/goods.ts 组合式
import { defineStore } from "pinia";
import {computed, ref} from "vue";
export const useGoodsStore = defineStore('goods',() => {
const goods = ref({name: '', price: 0})
const goodsStr = computed(() => goods.value.name + ":" + goods.value.price + "元")
function updateGoodsInfo(name: string,price: number) {
goods.value.name = name
goods.value.price = price
}
return { goods, goodsStr, updateGoodsInfo }
})
1 Pinia基础
store 是一个用reactive包装的对象,不能对它进行解构,否则属性会失去响应性。可以使用storeToRefs()函数包装store,然后再进行解构,这样属性就仍具有响应性:
const userStore = useUserStore()
// const { name } = userStore // name不具有响应性
const { name } = storeToRefs(userStore) // name 具有响应性
1.1 State
使用选项式API时,可以通过调用store的$reset()方法将state重置为初始值。(在$reset()内部,会调用state()函数来创建一个新的状态对象,并用它替换当前状态。)
如果使用组合式API,需要在定义state时,创建自己的$reset()方法。
export const useGoodsStore = defineStore('goods',() => {
// 省略其他代码
function $reset() {
goods.value = {name: '', price: 0}
}
return { goods, goodsStr,$reset, updateGoodsInfo }
})
变更state,可以调用$patch方法,该方法接收一个对象,用于替换当前的state。也接受一个函数(参数为state),来修改state的值。
function patchUpdate() {
// 直接传入一个对象
userStore.$patch({
name: '刘女士',
address: '东莞'
})
// 或者传入一个函数
goodsStore.$patch((state) => {
state.goods.name = '蓝莓'
state.goods.price = 7
})
}
1.1.1 订阅State
可以通过store的$subscribe()方法侦听state及其变化。比起普通的watch(),它的好处是subscriptions在patch后只触发一次。
userStore.$subscribe((mutation, state) => {
console.log('$subscribe',mutation,state)
})
1.2 Actions
可以通过store.$onAction()来监听action和它们的结果。传递给它的回调函数会在action本身之前前执行。参数是包含store、after及onError等属性的对象。after表示允许你在action解决后执行一个回调函数,OnError允许你在action抛出错误或reject时执行一个回调函数。
goodsStore.$onAction((
{
name, // action 名称
store, // store 实例,类似 `goodsStore`
args, // 传递给 action 的参数数组
after, // 在 action 返回或解决后的钩子
onError, // action 抛出或拒绝的钩子
}) => {
console.log('$onAction,action执行前执行',name,store,args)
after((res) => {
console.log('action执行完后再执行:',res)
})
onError((err) => {
console.log("action报错时执行",err)
})
})
1.3 插件
是一个函数,通过pinia.use()这个函数传递给pinia。插件接收一个可选参数context。该参数是一个包含app、pinia、store等实例的对象。
- 如果这个函数有返回值,返回值为一个对象,则该对象的所有属性都会被添加到每个store上。
- 每创建一个store实例,这个插件函数都会执行一遍。
pinia.use((context) => {
console.log('pinia插件',context)
return {
type: context.store.$id + 'Plugin'
}
})
1.3.1 添加新的state
必须同时在两个地方添加这个属性。
- 在store上,这样才可以用store.att 访问它。
- 在store.$state 上,然后才可以在devtools中使用它,并且在SSR时被正确序列化。
pinia.use((context) => {
if (!context.store.$state.hasOwnProperty('other')) {
context.store.$state.other = ref('')
}
context.store.other = toRef(context.store.$state, 'other')
context.store.other = '其他信息'
// 省略其他代码
})
1.3.2 重置插件中添加的state
默认情况下,$reset()不会重置插件添加的state,但是可以重写它来重置添加的state。
pinia.use((context) => {
// 省略其他代码
const originalReset = context.store.$reset.bind(context.store)
return {
// 省略其他代码
$reset() {
originalReset()
context.store.other = ''
}
}
})
1.3.3 TypeScript与插件
1)标注插件类型
function customPiniaPlugin(context:PiniaPluginContext) {
// 省略其他代码
}
pinia.use(customPiniaPlugin)
2)为新的store属性添加类型
declare module 'pinia' {
export interface PiniaCustomProperties {
customInfo: string
}
}
function customPiniaPlugin({ store }:PiniaPluginContext) {
store.customInfo = 'hello'
}
3)为新的state添加类型。
declare module 'pinia' {
export interface PiniaCustomStateProperties<S> {
hello: string
}
}
pinia.use(({ store }) => {
store.$state.hello = '12'
})