109.vue中的getter函数和action函数的区别

这是一个绝佳的问题,因为它直接问到了 Pinia(以及 Vue 本身)最核心的设计哲学。
如果把 Store 比作一个计算器,这三个部分的分工是这样的:
|
部分 |
计算器类比 |
职责 |
能不能改数据? |
|---|---|---|---|
|
State |
显示屏上的数字 |
存放数据(比如 |
不直接改 |
|
Getters |
查看/统计按钮(比如“显示平方”) |
读取和计算数据(派生状态) |
绝对不能(只读) |
|
Actions |
操作按钮(+、-、清零) |
修改数据(业务逻辑) |
完全可以(写) |
一、核心区别一句话版
Getters 负责“算”(Read),Actions 负责“改”(Write)。
二、你的代码逐行解析(看本质)
1️⃣ Getters:只负责“算”,不负责“改”
getters: {
getCount: (state) => "当前Count:" + state.count,
doubleCount(state) {
return this.getCount + state.count
}
}
-
它们在干嘛?
-
getCount:把count包装成一句话。 -
doubleCount:基于count计算出一个新的值。
-
-
关键点:
-
它们没有修改
state.count的值。 -
即使你调用
store.doubleCount一百次,store.count依然是10。 -
它们就像是镜子,只是反射出数据的不同样子。
-
2️⃣ Actions:专门负责“改”
actions: {
increment() {
this.count++ // 直接修改 State
},
decrement() {
this.count-- // 直接修改 State
}
}
-
它们在干嘛?
-
increment:让count增加。 -
decrement:让count减少。
-
-
关键点:
-
它们的核心任务就是改变 State。
-
它们必须是普通函数(这样才能用
this指向 Store)。 -
它们可以包含任何复杂的业务逻辑(比如发送请求、处理数据)。
-
三、为什么要把“算”和“改”分开?(设计意义)
1. 职责清晰(好维护)
-
如果你想获取数据,你去
getters里找。 -
如果你想改变数据,你去
actions里找。 -
这就像冰箱的门(拿东西)和电源开关(通电/断电)是分开的,逻辑不乱。
2. 性能优化(Getters 有缓存)
getters是有缓存的。
// 组件里
console.log(store.doubleCount)
console.log(store.doubleCount)
console.log(store.doubleCount)
-
如果
count没变,上面的代码只会计算 1 次。 -
如果把这些计算逻辑写在
actions里,每次调用都会重新计算,浪费性能。
3. 逻辑复用
-
getters可以在多个组件中复用同一个计算逻辑。 -
actions可以在多个组件中复用同一个业务操作(比如“登录”、“下单”)。
四、一个生动的场景对比
假设我们要做一个“购物车”:
-
State:
items: [{ price: 10, qty: 2 }, { price: 20, qty: 1 }] -
Getters (负责算总价):
totalPrice: (state) => { return state.items.reduce((sum, item) => sum + item.price * item.qty, 0) }-
调用
store.totalPrice,返回40。 -
State 没变,只是算出了结果。
-
-
Actions (负责加商品):
addItem(newItem) { this.items.push(newItem) // 直接修改了 State }-
调用
store.addItem(...)。 -
State 变了(数组多了一项)。
-
因为 State 变了,
store.totalPrice会自动更新为新的总价。
-
五、在组件里怎么用?(实战)
<template>
<div>
<p>当前值:{{ store.count }}</p>
<p>描述:{{ store.getCount }}</p>
<p>两倍:{{ store.doubleCount }}</p>
<button @click="store.increment()">+1</button>
<button @click="store.decrement()">-1</button>
</div>
</template>
<script setup>
import { useCountStore } from '../store/countstore'
const store = useCountStore()
</script>
注意调用方式的不同:
-
Getters 像属性:
store.getCount(不用加括号) -
Actions 像方法:
store.increment()(必须加括号)
六、总结(背下来)
|
特性 |
Getters |
Actions |
|---|---|---|
|
角色 |
计算属性 (Computed) |
处理函数 (Methods) |
|
目的 |
读取、过滤、计算数据 |
修改数据、执行业务逻辑 |
|
能否改 State |
❌ 绝对不能 |
✅ 完全可以 |
|
是否有缓存 |
✅ 有 |
❌ 无 |
|
参数 |
接收 |
接收自定义参数 |
|
|
普通函数可用 |
必须用普通函数 |
|
组件调用 |
|
|
终极口诀:
Getters 只读不改,Actions 专责修改。
想拿数据找 Getters,想变数据找 Actions。
现在再看你的代码,是不是觉得 increment放在 actions里,而 doubleCount放在 getters里,简直是天作之合?这就是 Pinia 设计的优雅之处。👍
这是一个绝佳的问题,因为它直接问到了 Pinia(以及 Vue 本身)最核心的设计哲学。
如果把 Store 比作一个计算器,这三个部分的分工是这样的:
|
部分 |
计算器类比 |
职责 |
能不能改数据? |
|---|---|---|---|
|
State |
显示屏上的数字 |
存放数据(比如 |
不直接改 |
|
Getters |
查看/统计按钮(比如“显示平方”) |
读取和计算数据(派生状态) |
绝对不能(只读) |
|
Actions |
操作按钮(+、-、清零) |
修改数据(业务逻辑) |
完全可以(写) |
一、核心区别一句话版
Getters 负责“算”(Read),Actions 负责“改”(Write)。
二、你的代码逐行解析(看本质)
1️⃣ Getters:只负责“算”,不负责“改”
getters: {
getCount: (state) => "当前Count:" + state.count,
doubleCount(state) {
return this.getCount + state.count
}
}
-
它们在干嘛?
-
getCount:把count包装成一句话。 -
doubleCount:基于count计算出一个新的值。
-
-
关键点:
-
它们没有修改
state.count的值。 -
即使你调用
store.doubleCount一百次,store.count依然是10。 -
它们就像是镜子,只是反射出数据的不同样子。
-
2️⃣ Actions:专门负责“改”
actions: {
increment() {
this.count++ // 直接修改 State
},
decrement() {
this.count-- // 直接修改 State
}
}
-
它们在干嘛?
-
increment:让count增加。 -
decrement:让count减少。
-
-
关键点:
-
它们的核心任务就是改变 State。
-
它们必须是普通函数(这样才能用
this指向 Store)。 -
它们可以包含任何复杂的业务逻辑(比如发送请求、处理数据)。
-
三、为什么要把“算”和“改”分开?(设计意义)
1. 职责清晰(好维护)
-
如果你想获取数据,你去
getters里找。 -
如果你想改变数据,你去
actions里找。 -
这就像冰箱的门(拿东西)和电源开关(通电/断电)是分开的,逻辑不乱。
2. 性能优化(Getters 有缓存)
getters是有缓存的。
// 组件里
console.log(store.doubleCount)
console.log(store.doubleCount)
console.log(store.doubleCount)
-
如果
count没变,上面的代码只会计算 1 次。 -
如果把这些计算逻辑写在
actions里,每次调用都会重新计算,浪费性能。
3. 逻辑复用
-
getters可以在多个组件中复用同一个计算逻辑。 -
actions可以在多个组件中复用同一个业务操作(比如“登录”、“下单”)。
四、一个生动的场景对比
假设我们要做一个“购物车”:
-
State:
items: [{ price: 10, qty: 2 }, { price: 20, qty: 1 }] -
Getters (负责算总价):
totalPrice: (state) => { return state.items.reduce((sum, item) => sum + item.price * item.qty, 0) }-
调用
store.totalPrice,返回40。 -
State 没变,只是算出了结果。
-
-
Actions (负责加商品):
addItem(newItem) { this.items.push(newItem) // 直接修改了 State }-
调用
store.addItem(...)。 -
State 变了(数组多了一项)。
-
因为 State 变了,
store.totalPrice会自动更新为新的总价。
-
五、在组件里怎么用?(实战)
<template>
<div>
<p>当前值:{{ store.count }}</p>
<p>描述:{{ store.getCount }}</p>
<p>两倍:{{ store.doubleCount }}</p>
<button @click="store.increment()">+1</button>
<button @click="store.decrement()">-1</button>
</div>
</template>
<script setup>
import { useCountStore } from '../store/countstore'
const store = useCountStore()
</script>
注意调用方式的不同:
-
Getters 像属性:
store.getCount(不用加括号) -
Actions 像方法:
store.increment()(必须加括号)
六、总结(背下来)
|
特性 |
Getters |
Actions |
|---|---|---|
|
角色 |
计算属性 (Computed) |
处理函数 (Methods) |
|
目的 |
读取、过滤、计算数据 |
修改数据、执行业务逻辑 |
|
能否改 State |
❌ 绝对不能 |
✅ 完全可以 |
|
是否有缓存 |
✅ 有 |
❌ 无 |
|
参数 |
接收 |
接收自定义参数 |
|
|
普通函数可用 |
必须用普通函数 |
|
组件调用 |
|
|
终极口诀:
Getters 只读不改,Actions 专责修改。
想拿数据找 Getters,想变数据找 Actions。
现在再看你的代码,是不是觉得 increment放在 actions里,而 doubleCount放在 getters里,简直是天作之合?这就是 Pinia 设计的优雅之处。👍
我们来看下面的代码
countstore.js
import { defineStore } from 'pinia'
/**
* 定义一个名为 count 的 Store
* 使用 Option Store(选项式)写法
*/
const piniaCountStore = defineStore('count', {
state(){
return {
count:10
}
}
,
getters:
{
getCount(state){
return "当前count的值"+state.count
},
doubleCount(state){
return this.getCount+state.count
}
},
actions:{
addCount(state){
this.count +=10
},
decrease(state){
this.count-=5
}
}
}
)
export default piniaCountStore
app.vue
<template> <h1>app vue</h1> <hello /> </template> <script setup> // 引入子组件 import hello from './components/hello.vue' </script> <style scoped> h1 { color: #42b983; } </style>
hello.vue
<template>
<p>hello.vue</p>
<p>count: {{ store.count }}</p>
<p>hello22.vue</p>
<p>count: {{ store.doubleCount }}</p>
<p>{{ store.getCount }}</p>
<!-- 可选:修改数据 -->
<button @click="store.count++">+1</button>
<button @click="store.addCount">+10</button>
<button @click="store.decrease">-5</button>
</template>
<script setup>
// 引入 store
import piniaCountStore from '../store/countstore'
// 调用 store(注意:是函数调用)
const store = piniaCountStore()
</script>
<style scoped>
p {
font-size: 18px;
}
</style>
程序的运行效果如下所示:

当点击-5的按钮之后效果如下所示

posted on 2026-07-14 20:41 luzhouxiaoshuai 阅读(7) 评论(0) 收藏 举报
浙公网安备 33010602011771号