pinia 官网
pinia 是 Vuex 的升级版,被誉为 vuex5。官网也说过,为了尊重原作者,所以取名 pinia,而没有使用 Vuex。
关于 vuex 的学习请参阅此文。
pinia 是一种 状态管理 工具。它是 Vue 的存储库,它允许您跨组件/页面共享状态。
pinia 的优势、特点:
npm i pinia -S
import { createPinia } from 'pinia'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
在项目的 src 目录下新建一个 stores 文件夹,用于专门放置 pinia 的文件。
然后,在 stores 文件夹下新建一个 counter.ts 文件,在该文件中创建一个 Store:
import { defineStore } from 'pinia'
// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++
}
}
})
在组件中使用这个 Store:
<script lang="ts">
import { useStore } from '@/stores/counter'
export default {
setup() {
const store = useStore()
return {
// 您可以返回整个 store 实例以在模板中使用它
store,
}
},
}
</script>
<template lang="pug">
.number {{store.count}}
</template>
下文中的所有 store 都代指用户自定义的 Store 的实例,该 Store 实例的名字不是唯一的,可以自取。
Pinia 支持插件来扩展自身功能。可参阅官网 Pinia Plugins。
Pinia 插件的本质是一个 JavaScript 函数。该函数接收一个可选的参数 context。可以选择返回要添加到 store 的属性。
例如:
export function myPiniaPlugin(context) {
context.pinia // 使用 `createPinia()` 创建的 pinia
context.app // 使用 `createApp()` 创建的当前应用程序(仅限 Vue 3)
context.store // 插件正在扩充的 store
context.options // 定义存储的选项对象传递给`defineStore()`
// ...
}
使用 pinia.use() 可以将 Pinia 插件添加到 pinia 实例中去。
例如:
import { createPinia } from 'pinia'
const pinia = createPinia()
pinia.use(myPiniaPlugin)
本小节仅列取部分常用的 Pinia 函数。全部的请参阅 Pinia 官网 API 之函数。
createPinia() 方法用于创建一个 Pinia 实例。返回这个 Pinia 实例。
defineStore() 方法用于创建一个检索 store 实例的 useStore 函数。
defineStore() 方法可以接收 2 个参数:
mapActions() 方法,通过生成要在组件的 methods 字段中铺开的对象,允许直接使用存储(store)中的操作(action),而不使用合成API (setup())。对象的值是操作(action),而键是结果方法的名称。
mapActions() 方法可以接收 2 个参数:
例如:
export default {
methods: {
// 其他方法属性
// useCounterStore 有两个操作(action),分别叫做 `increment` 和 `setCount`
...mapActions(useCounterStore, { moar: 'increment', setIt: 'setCount' })
},
created() {
this.moar()
this.setIt(2)
}
}
mapState() 方法,通过生成要在组件的 computed 字段中展开的对象,以允许从一个没有使用组合式 API (setup()) 的 store 使用 state 和 getters 对象的值是状态 properties/getters ,而键是结果计算属性的名称。您也可以传递一个自定义函数,该函数将接收 store 作为其第一个参数。请注意,虽然它可以通过这个访问组件实例,但它不会识别类型。
mapState() 方法可以接收 2 个参数:
例如:
export default {
computed: {
// 其它计算属性
// useCounterStore 有一个 state 属性叫做 `count` 和一个 getter 叫做 `double`
...mapState(useCounterStore, {
n: 'count',
triple: store => store.n * 3,
// 注意如果我们想使用 `this` 则不能使用箭头函数
custom(store) {
return this.someComponentValue + store.n
},
doubleN: 'double'
})
},
created() {
this.n // 2
this.doubleN // 4
}
}
mapStores() 方法,通过生成要在组件的 computed 字段中展开的对象,允许使用没有组合式API (setup())的存储。它接受 store 定义的列表。
mapStores() 方法可以接收 1 个参数:
例如:
export default {
computed: {
// 其它计算属性
...mapStores(useUserStore, useCartStore)
},
created() {
this.userStore // id为"user"的存储
this.cartStore // id为"cart"的存储
}
}
当使用 store 的过程中,如果直接对 store 进行解构,会破坏数据的响应,所以 pinia 提供了 storeToRefs 用来进行解构。
storeToRefs() 方法,用 store 的所有state、getters和 插件添加的(plugin-added)state、 属性(properties)创建一个引用对象。类似于toRefs(),但专门为 Pinia store 设计。
storeToRefs() 方法可以接收 1 个参数:
例如:
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/store/counterStore'
export default {
setup() {
const counterStore = useCounterStore()
// 可以解构actions
const { increment } = counterStore
const { count } = storeToRefs(counterStore)
return {
count,
increment,
}
}
}
【推荐文章】
pinia源码
【参考文章】
Pinia 入门
一文搞懂pinia状态管理(保姆级教程)
Pinia基础知识
新一代状态管理工具,Pinia.js 上手指南
【精品】pinia详解
Pinia进阶:优雅的setup(函数式)写法+封装