Pinia 是 Vue 官方推荐的状态管理库,相比 Vuex 更加简洁易用。我会分步骤教你如何在组件中获取和修改 Pinia 的状态,全程使用通俗易懂的方式讲解,确保你能快速上手。
一、前置准备:创建一个 Pinia Store
首先需要先创建一个基础的 Store,后续所有操作都基于这个示例:
javascript
运行
// stores/counter.js
import { defineStore } from 'pinia'
// 定义并导出 Store(命名规则:use + 名称 + Store)
export const useCounterStore = defineStore('counter', {
// state 是存储状态的地方,必须是函数(避免跨实例污染)
state: () => ({
count: 0,
message: 'Hello Pinia'
}),
// 可选:getters 用于计算属性(类似组件的 computed)
getters: {
doubleCount: (state) => state.count * 2
},
// 可选:actions 用于修改状态(支持同步/异步)
actions: {
increment() {
this.count++ // 直接修改 state
},
incrementBy(num) {
this.count += num
},
async asyncIncrement() {
// 模拟异步操作(如接口请求)
await new Promise(resolve => setTimeout(resolve, 1000))
this.count++
}
}
})
同时确保你已经在项目入口文件(如
main.js)挂载了 Pinia:javascript
运行
// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia()) // 挂载 Pinia
app.mount('#app')
二、在组件中获取 Pinia 状态
获取状态有 3 种常用方式,你可以根据场景选择:
方式 1:直接获取(最简单,推荐日常使用)
vue
<template>
<div>
<p>当前计数:{{ counterStore.count }}</p>
<p>双倍计数:{{ counterStore.doubleCount }}</p>
<p>消息:{{ counterStore.message }}</p>
</div>
</template>
<script setup>
// 1. 导入创建好的 Store
import { useCounterStore } from '@/stores/counter'
// 2. 实例化 Store(注意:每次调用都是同一个实例,无需担心重复创建)
const counterStore = useCounterStore()
</script>
方式 2:解构获取(需用 storeToRefs 保持响应式)
如果直接解构
counterStore,会丢失响应式,必须用 Pinia 提供的 storeToRefs:vue
<template>
<div>
<p>当前计数:{{ count }}</p>
<p>消息:{{ message }}</p>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia' // 导入辅助函数
const counterStore = useCounterStore()
// 解构并保持响应式
const { count, message } = storeToRefs(counterStore)
</script>
方式 3:获取 Getters(计算属性)
Getters 会自动缓存,依赖的 state 变化时才重新计算,获取方式和普通 state 一致:
vue
<template>
<p>双倍计数:{{ counterStore.doubleCount }}</p>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const counterStore = useCounterStore()
// 也可以解构 Getters(同样需要 storeToRefs)
// const { doubleCount } = storeToRefs(counterStore)
</script>
三、在组件中修改 Pinia 状态
Pinia 修改状态有 3 种方式,核心原则:推荐用 actions 修改(规范),简单场景可直接修改。
方式 1:直接修改(最简单,适合简单场景)
Pinia 允许直接修改 state(无需像 Vuex 那样写 mutations):
vue
<template>
<button @click="counterStore.count++">直接加 1</button>
<button @click="counterStore.message = '新消息'">修改消息</button>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const counterStore = useCounterStore()
</script>
方式 2:通过 actions 修改(推荐,适合复杂逻辑 / 团队协作)
actions 支持同步 / 异步,是修改状态的 “规范方式”,便于统一管理和调试:
vue
<template>
<button @click="counterStore.increment()">通过 action 加 1</button>
<button @click="counterStore.incrementBy(5)">加 5</button>
<button @click="counterStore.asyncIncrement()">异步加 1</button>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const counterStore = useCounterStore()
</script>
方式 3:批量修改($patch 方法,适合多状态批量更新)
如果需要一次性修改多个状态,用
$patch 更高效(减少响应式更新次数):vue
<template>
<button @click="batchUpdate">批量修改状态</button>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const counterStore = useCounterStore()
const batchUpdate = () => {
// 方式 A:对象形式(简单批量修改)
counterStore.$patch({
count: counterStore.count + 10,
message: '批量修改后的消息'
})
// 方式 B:函数形式(适合复杂逻辑,如数组操作)
// counterStore.$patch((state) => {
// state.count += 10
// state.message = '批量修改后的消息'
// })
}
</script>
额外:重置状态(恢复初始值)
如果需要把 state 恢复到初始状态,用
$reset 方法:vue
<template>
<button @click="counterStore.$reset()">重置状态</button>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const counterStore = useCounterStore()
</script>
总结
- 获取状态:先导入并实例化 Store,直接访问
store.状态名;解构时必须用storeToRefs保持响应式。 - 修改状态:简单场景可直接修改
store.状态名,复杂逻辑 / 团队项目推荐用actions,批量修改用$patch。 - 核心优势:Pinia 无需 mutations,语法更简洁,支持同步 / 异步 actions,解构时注意用
storeToRefs保留响应式。