什么是Pinia
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。它提供了类似于 Vuex 的功能,但比 Vuex 更加简单和直观。
需要在多个组件之间共享状态或数据时使用 Pinia 的 store,这样可以避免 props 和 eventBus 等传统方法的复杂性,使状态管理更加集中和可维护。
安装
- 在终端中输入
npm install pinia
; - 在main.js中引入
pinia
,并且通过app.use()
安装;
javascript
import { createApp } from 'vue'
import { createPinia } from 'pinia' // 引入
import App from './App.vue'
const pinia = createPinia() // 创建实例
const app = createApp(App)
app.use(pinia) // 安装使用
app.mount('#app')
定义Store
一般会在 store 目录下创建相应模块名字的js文件中定义; 例如:定义 user 模块要用到的 store,首先创建 /src/store/demo.js
文件。
接着使用 defineStore 方法定义 store:
-
defineStore
定义的返回值(示例中的useDemoStore
)可以自己任意命名,但是建议以 use + store名字 + Store 的形式来定义(例如:useUser Store、useCartStore...)。 -
defineStore
的第一个参数是应用中 Store 的唯一 ID(示例中的"demo")。 -
defineStore
的第二个参数可接受两类值:Setup 函数 或 Option 对象,后面内容将只介绍 Option 对象。
javascript
// /src/store/demo.js
import { defineStore } from 'pinia'
export const useDemoStore = defineStore('demo', {
// 其他配置...
})
Option
State
state 是一个返回初始状态的函数。
javascript
// /src/store/demo.js
import { defineStore } from 'pinia'
export const useDemoStore = defineStore('demo', {
state: () => {
return { // 在返回对象中定义要使用的数据
count: 0,
name: 'd2school',
isAdmin: true,
arr: [1,2,3]
}
},
})
访问state
使用定义的 store 实例就可以直接对其 state 进行读写 。 例如:上面定义的 store 返回值是 useDemoStore
,那么使用方式为:
javascript
import {useDemoStore} from "/src/store/demo.js";
const demoStore = useDemoStore() // store实例
store.name // 'd2school' 访问到state的内容
store.count++ // 1 进行修改
变更state
除了 store.count++
直接对 state 进行修改,也可以使用 $patch
同时更改多个属性。
javascript
demoStore.$patch({
count: demoStore.count + 1,
name: 'd2school.com',
isAdmin: false,
})
使用这种语法时,某些变更会比较麻烦或者耗时。 例如:对数组的增删操作,都需要创建一个新的集合,因此 $patch
方法也接受一个函数来进行变更。
javascript
demoStore.$patch((state) => {
state.arr.push(3)
state.isAdmin= false
})
重置state
使用 store 实例的 $reset()
方法可以将 state 重置为初始值。
javascript
import {useDemoStore} from "/src/store/demo.js";
const demoStore = useStore() // store实例
demoStore.$reset() // 重置
Getter
getter 是 state 的计算值,建议使用箭头函数,它将接收 state
作为第一个参数。
在 getter 中可以使用 this 访问到整个 store 实例。
javascript
// /src/store/count.js
export const useCountStore = defineStore('count', {
state: () => ({
count: 1,
}),
getters: {
// 返回2倍数的count
doubleCount(state) {
return state.count * 2
},
// 返回两倍的count并且+1
doublePlusOne(){
return this.doubleCount + 1 // 可以使用this访问到整个store实例
},
},
})
直接在 store 实例上访问 getter。
vue
<script setup>
import { useCounterStore } from '/src/store/counterStore.js'
const countStore = useCountStore ()
countStore.doubleCount // 2
countStore.doublePlusOne // 3
</script>
<template>
<p>{{ store.count}}</p>
<p>{{ store.doubleCount }}</p>
</template>
Action
action 相当于组件的 methods,可以执行异步操作,处理业务逻辑。
javascript
import {defineStore} from 'pinia'
export const useDemoStore = defineStore('demo', {
// 其他配置...
state: () => {
return {
count: 0
}
},
actions: {
modifyCount(val) {
this.count = val < 5 ? val : 0 // val小于5则赋值val否则赋值0
}
}
})
同样可以直接在 store 实例上访问 actions。
javascript
import {useDemoStore} from "./store/demo.js";
import {ref} from "vue";
const store = useDemoStore()
let count = ref(0)
function change() {
count.value++
store.modifyCount(count.value)
}