什么是Pinia
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。它提供了类似于 Vuex 的功能,但比 Vuex 更加简单和直观。
需要在多个组件之间共享状态或数据时使用 Pinia 的 store,这样可以避免 props 和 eventBus 等传统方法的复杂性,使状态管理更加集中和可维护。
安装
- 在终端中输入
npm install pinia
; - 在main.js中引入
pinia
,并且通过app.use()
安装;
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 的形式来定义(例如:useUserStore、useCartStore…)。 -
defineStore
的第一个参数是应用中 Store 的唯一 ID(示例中的"demo")。 -
defineStore
的第二个参数可接受两类值:Setup 函数或 Option 对象,后面内容将只介绍 Option 对象。
// /src/store/demo.jsimport { defineStore } from 'pinia'export const useDemoStore = defineStore('demo', {// 其他配置...
})
Option
State
state 是一个返回初始状态的函数。
// /src/store/demo.jsimport { 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
,那么使用方式为:
import {useDemoStore} from "/src/store/demo.js";const demoStore = useDemoStore() // store实例store.name // 'd2school' 访问到state的内容
store.count++ // 1 进行修改
变更state
除了 store.count++
直接对 state 进行修改,也可以使用 $patch
同时更改多个属性。
demoStore.$patch({count: demoStore.count + 1,name: 'd2school.com',isAdmin: false,
})
使用这种语法时,某些变更会比较麻烦或者耗时。
例如:对数组的增删操作,都需要创建一个新的集合,因此 $patch
方法也接受一个函数来进行变更。
demoStore.$patch((state) => {state.arr.push(3)state.isAdmin= false
})
重置state
使用 store 实例的 $reset()
方法可以将 state 重置为初始值。
import {useDemoStore} from "/src/store/demo.js";const demoStore = useStore() // store实例demoStore.$reset() // 重置
Getter
getter 是 state 的计算值,建议使用箭头函数,它将接收 state
作为第一个参数。
在 getter 中可以使用 this 访问到整个 store 实例
// /src/store/count.js
export const useCountStore = defineStore('count', {state: () => ({count: 1,}),getters: {// 返回2倍数的countdoubleCount(state) {return state.count * 2},// 返回两倍的count并且+1doublePlusOne(){return this.doubleCount + 1 // 可以使用this访问到整个store实例},
},
})
直接在 store 实例上访问 getter。
<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,可以执行异步操作,处理业务逻辑。
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。
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)
}