Pinia 是 Vue.js 的官方状态管理库,它取代了 Vuex,提供了更简洁、直观且类型友好的 API。以下是 Pinia 中最常用的核心 API 及其用法:
1. defineStore()
- 定义 Store
这是创建一个 store 的核心 API。它接受一个唯一的 ID 和一个配置对象(或 setup 函数)。
javascript
javascript
深色版本
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
// 状态 (State)
state: () => ({
count: 0,
name: 'Eduardo'
}),
// 计算属性 (Getters)
getters: {
doubleCount: (state) => state.count * 2,
// 带参数的 getter
getByName: (state) => {
return (name) => state.name === name
}
},
// 动作 (Actions)
actions: {
increment() {
this.count++
},
decrement() {
this.count--
},
// 异步操作
async fetchUser() {
const res = await fetch('/api/user')
this.name = await res.json()
}
}
})
说明 :
defineStore
返回一个函数(如useCounterStore
),调用它即可获取 store 实例。
2. state
- 状态
用于定义 store 中的响应式数据。
- 必须是一个函数,返回一个包含状态的对象。
- 可以在组件中直接读取和修改。
yaml
javascript
深色版本
state: () => ({
count: 0,
todos: []
})
3. getters
- 计算属性
类似于 Vue 组件中的 computed,用于派生状态。
- 接收
state
作为第一个参数。 - 支持缓存,只有依赖的 state 变化时才会重新计算。
- 可以接受参数(返回一个函数)。
javascript
javascript
深色版本
getters: {
// 基础 getter
doubleCount: (state) => state.count * 2,
// 带参数的 getter
getTodoById: (state) => {
return (id) => state.todos.find(todo => todo.id === id)
}
}
4. actions
- 动作
用于定义修改 state 的方法,支持同步和异步操作。
- 可以通过
this
访问state
、getters
和其他actions
。 - 是修改 state 的唯一推荐方式(虽然可以直接修改,但不推荐)。
javascript
javascript
深色版本
actions: {
increment() {
this.count++
},
async fetchData() {
const data = await api.getData()
this.todos = data
}
}
5. 在组件中使用 Store
在组件中通过调用 useXxxStore()
函数来使用 store。
xml
vue
深色版本
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
// 直接访问 state, getters, actions
console.log(counter.count) // state
console.log(counter.doubleCount) // getter
counter.increment() // action
</script>
<template>
<div>
<p>Count: {{ counter.count }}</p>
<p>Double: {{ counter.doubleCount }}</p>
<button @click="counter.increment">+</button>
</div>
</template>
注意 :从 store 中解构变量会失去响应性 。如果需要解构,应使用
storeToRefs()
。
6. storeToRefs()
- 保持解构后的响应性
当你想从 store 中解构 state 或 getters 并保持响应性时,使用此工具函数。
xml
vue
深色版本
<script setup>
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
// ❌ 错误:count 失去响应性
// const { count, doubleCount } = counter
// ✅ 正确:使用 storeToRefs
const { count, doubleCount } = storeToRefs(counter)
const { increment } = counter // actions 不需要,因为不是响应式引用
</script>
7. mapState
, mapGetters
, mapActions
- 映射辅助函数
在选项式 API(Options API)中,可以使用这些辅助函数将 store 的内容映射到组件中。
javascript
javascript
深色版本
import { mapState, mapActions } from 'pinia'
import { useCounterStore } from '@/stores/counter'
export default {
computed: {
// 映射 state
...mapState(useCounterStore, ['count', 'name']),
// 或者重命名
...mapState(useCounterStore, {
myCount: 'count'
})
},
methods: {
// 映射 actions
...mapActions(useCounterStore, ['increment', 'fetchUser'])
}
}
8. $reset()
- 重置状态
每个 store 实例都暴露一个 $reset()
方法,用于将 state 重置为初始值。
scss
javascript
深色版本
const counter = useCounterStore()
counter.$reset() // 将 count 重置为 0
9. $subscribe()
- 订阅状态变化
监听 store 的 state 变化,类似于 Vuex 的 subscribe。
javascript
javascript
深色版本
const counter = useCounterStore()
// 订阅 state 变化
const unsubscribe = counter.$subscribe((mutation, state) => {
// mutation: 包含 type 等信息
// state: 最新的 state
console.log('State changed:', state.count)
})
// 取消订阅
// unsubscribe()
总结
API | 用途 |
---|---|
defineStore() |
定义一个 store |
state |
定义响应式数据 |
getters |
定义计算属性 |
actions |
定义修改 state 的方法(支持异步) |
useXxxStore() |
在组件中使用 store |
storeToRefs() |
解构 store 时保持响应性 |
mapState / mapGetters / mapActions |
选项式 API 中的映射辅助函数 |
$reset() |
重置 state 到初始值 |
$subscribe() |
监听 state 变化 |