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

image

 

这是一个绝佳的问题,因为它直接问到了 Pinia(以及 Vue 本身)最核心的设计哲学。

如果把 Store 比作一个计算器,这三个部分的分工是这样的:

 

部分

计算器类比

职责

能不能改数据?

State

显示屏上的数字

存放数据(比如 count: 10

不直接改

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

绝对不能

完全可以

是否有缓存

✅ 有

❌ 无

参数

接收 state

接收自定义参数

this

普通函数可用 this

必须用普通函数

组件调用

store.xxx(属性)

store.xxx()(方法)

终极口诀:

Getters 只读不改,Actions 专责修改。

想拿数据找 Getters,想变数据找 Actions。

现在再看你的代码,是不是觉得 increment放在 actions里,而 doubleCount放在 getters里,简直是天作之合?这就是 Pinia 设计的优雅之处。👍

 

这是一个绝佳的问题,因为它直接问到了 Pinia(以及 Vue 本身)最核心的设计哲学。

如果把 Store 比作一个计算器,这三个部分的分工是这样的:

 

部分

计算器类比

职责

能不能改数据?

State

显示屏上的数字

存放数据(比如 count: 10

不直接改

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

绝对不能

完全可以

是否有缓存

✅ 有

❌ 无

参数

接收 state

接收自定义参数

this

普通函数可用 this

必须用普通函数

组件调用

store.xxx(属性)

store.xxx()(方法)

终极口诀:

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>

程序的运行效果如下所示:

image

 

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

image

 

posted on 2026-07-14 20:41  luzhouxiaoshuai  阅读(7)  评论(0)    收藏  举报

导航