首页
/ Pinia核心概念:Actions详解与应用指南

Pinia核心概念:Actions详解与应用指南

2025-07-06 02:25:20作者:丁柯新Fawn

什么是Actions

在Pinia状态管理库中,Actions相当于组件中的methods,用于封装业务逻辑。与Vue组件中的methods类似,Actions允许你定义各种操作来修改状态(state),但提供了更强大的功能和更灵活的用法。

基本用法

在defineStore()中使用actions属性定义Actions:

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
  }),
  actions: {
    increment() {
      this.count++
    },
    randomizeCounter() {
      this.count = Math.round(100 * Math.random())
    },
  },
})

注意:

  1. 不要使用箭头函数定义Actions,因为需要访问this
  2. this指向整个store实例,可以访问state、getters和其他actions
  3. 支持完整的类型推断和自动补全

异步Actions

Actions的一个重要特性是支持异步操作,你可以在其中使用await:

export const useUsers = defineStore('users', {
  state: () => ({
    userData: null,
  }),

  actions: {
    async registerUser(login, password) {
      try {
        this.userData = await api.post({ login, password })
        showTooltip(`Welcome back ${this.userData.name}!`)
      } catch (error) {
        showTooltip(error)
        return error
      }
    },
  },
})

异步Actions的典型使用场景包括:

  • API调用
  • 复杂业务逻辑处理
  • 多个状态变更的组合操作

调用Actions

Actions可以像普通方法一样被调用:

<script setup>
const store = useCounterStore()
// 调用action
store.randomizeCounter()
</script>

<template>
  <button @click="store.randomizeCounter()">随机化计数器</button>
</template>

跨Store访问

在Actions中可以方便地访问其他store:

import { useAuthStore } from './auth-store'

export const useSettingsStore = defineStore('settings', {
  actions: {
    async fetchUserPreferences() {
      const auth = useAuthStore()
      if (auth.isAuthenticated) {
        this.preferences = await fetchPreferences()
      } else {
        throw new Error('用户必须认证')
      }
    },
  },
})

与Options API配合使用

使用setup()方式

<script>
import { useCounterStore } from '../stores/counter'

export default defineComponent({
  setup() {
    const counterStore = useCounterStore()
    return { counterStore }
  },
  methods: {
    incrementAndPrint() {
      this.counterStore.increment()
      console.log('新计数:', this.counterStore.count)
    },
  },
})
</script>

使用mapActions辅助函数

import { mapActions } from 'pinia'
import { useCounterStore } from '../stores/counter'

export default {
  methods: {
    // 映射为this.increment()
    ...mapActions(useCounterStore, ['increment']),
    // 自定义方法名
    ...mapActions(useCounterStore, { myOwnName: 'increment' }),
  },
}

监听Actions

Pinia提供了$onAction方法来监听actions的执行:

const unsubscribe = store.$onAction(
  ({
    name,        // action名称
    store,       // store实例
    args,        // 传入的参数数组
    after,       // action成功后的钩子
    onError,     // action失败时的钩子
  }) => {
    const startTime = Date.now()
    console.log(`开始执行 "${name}",参数: [${args.join(', ')}]`)

    after((result) => {
      console.log(
        `"${name}" 执行完成,耗时 ${Date.now() - startTime}ms。结果: ${result}`
      )
    })

    onError((error) => {
      console.warn(
        `"${name}" 执行失败,耗时 ${Date.now() - startTime}ms。错误: ${error}`
      )
    })
  }
)

// 手动取消监听
unsubscribe()

默认情况下,action订阅会绑定到添加它们的组件上(如果store在组件的setup()中)。如果要在组件卸载后保持订阅,可以传递true作为第二个参数:

<script setup>
const someStore = useSomeStore()
// 组件卸载后仍保持订阅
someStore.$onAction(callback, true)
</script>

最佳实践

  1. 业务逻辑封装:将复杂的业务逻辑封装在actions中,保持组件的简洁性
  2. 错误处理:在异步actions中妥善处理错误,提供友好的错误提示
  3. 组合使用:一个action可以调用其他action,实现逻辑复用
  4. 适度拆分:避免编写过于庞大的action,保持单一职责原则
  5. 监听机制:合理使用$onAction进行调试和监控

通过合理使用Pinia的Actions,你可以构建出结构清晰、易于维护的状态管理代码,为应用开发带来极大的便利。