Pinia
Store 的三大核心 state、getters 与 actions
掌握 Pinia Store 的 state、getters、actions 三个核心概念,学会定义和使用 Pinia 的状态管理单元。
🎯 引言
学会这篇文章,你能搞清楚 Pinia Store 里的三个核心部分:state、getters、actions 分别负责什么。学完以后,你能够独立写出一个结构清晰、职责明确的 Store。
🧱 Store 的基本结构
一个 Store 通常长这样:
stores/counter.js
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
double() {
return this.count * 2;
},
},
actions: {
add() {
this.count++;
},
},
});
三部分分工:
- state:存数据
- getters:基于数据做计算
- actions:改数据或执行业务逻辑
可以把 Store 想象成一个小仓库:
state 是货架,getters 是价签/统计表,actions 是仓库操作员。📦 state 存放数据
state 必须是一个函数,返回一个对象。Pinia 会自动把这个对象变成响应式数据。
stores/user.js
export const useUserStore = defineStore('user', {
state: () => ({
name: '张三',
age: 20,
}),
});
在组件中读取:
<template>
<p>{{ user.name }},{{ user.age }} 岁</p>
</template>
<script setup>
import { useUserStore } from './stores/user.js';
const user = useUserStore();
</script>
state 一定要写成函数返回对象。如果直接写对象,多个应用实例可能会共享同一份数据,导致状态互相污染。⚡ getters 做计算
getters 里的方法会根据 state 计算出一个新值,并且有缓存。只要依赖的 state 不变,多次访问不会重复计算。
stores/user.js
export const useUserStore = defineStore('user', {
state: () => ({
firstName: '张',
lastName: '三',
}),
getters: {
fullName() {
return this.firstName + this.lastName;
},
},
});
使用:
<template>
<p>全名:{{ user.fullName }}</p>
</template>
getter 里用
this.xxx 访问 state。getter 之间也可以互相访问,比如 this.otherGetter。🛠 actions 改数据
actions 里定义修改 state 的方法。简单修改可以直接做,复杂逻辑可以封装起来。
stores/counter.js
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
actions: {
add() {
this.count++;
},
addN(n) {
this.count += n;
},
reset() {
this.count = 0;
},
},
});
组件中调用:
<template>
<p>{{ counter.count }}</p>
<button @click="counter.add">加一</button>
<button @click="counter.addN(5)">加五</button>
<button @click="counter.reset">重置</button>
</template>
在 action 里用
this.count 修改 state,不需要像 Vuex 那样提交 mutation。这是 Pinia 最省心的地方。💡 什么时候该用哪个
| 场景 | 用哪个 | 例子 |
|---|---|---|
| 存储原始数据 | state | count、userInfo |
| 需要基于数据计算 | getters | double、fullName |
| 修改数据或执行逻辑 | actions | add、login |
不要把所有逻辑都堆在组件里,也不要把所有修改都直接写在模板中。简单的状态读取和展示交给模板,状态的修改建议集中到 Store 的 actions 中。
🧾 小节总结
- Store 由
state、getters、actions三部分组成。 state是函数返回的响应式对象,用来存数据。getters是基于 state 的计算属性,有缓存。actions是用来修改 state 或处理业务逻辑的方法。- 简单修改可以直接做,复杂修改建议放到 action 中。
❓ 知识问答
Q1:getter 和 action 都能访问 state,它们有什么区别?
getter 是“只读”的,用来计算和返回派生值;action 是用来“改写”状态的。一个负责算,一个负责改。
Q2:getter 里能调用 action 吗?
不推荐。getter 应该保持纯计算,不要产生副作用。需要副作用的请用 action。
Q3:action 里能访问 getter 吗?
可以,用 this.xxx 即可。
Q4:state 里能放函数吗?
不建议。state 只放数据,函数放到 actions 中。
🧪 小练习
补全下面的 useTodoStore,实现:
todos数组,每项有id、text、done。finishedCountgetter 返回已完成数量。addTodo(text)action 添加新事项。toggle(id)action 切换对应事项的done。
stores/todo.js
import { defineStore } from 'pinia';
export const useTodoStore = defineStore('todo', {
state: () => ({
todos: [],
}),
getters: {
// 请在这里编写 finishedCount
},
actions: {
// 请在这里编写 addTodo 和 toggle
},
});
🎉 恭喜你掌握了 Store 的三大核心!下一篇我们学习在组件中如何正确使用 Store,尤其是避免响应式丢失。
