跳转到内容

Pinia Actions

来自代码酷

Pinia Actions[编辑 | 编辑源代码]

介绍[编辑 | 编辑源代码]

Pinia Actions 是 Pinia 状态管理库中用于封装业务逻辑的核心功能,类似于 Vuex 中的 mutations + actions 组合。Actions 允许您定义可复用的方法,这些方法可以:

  • 修改状态(通过直接访问 this
  • 执行异步操作(如 API 调用)
  • 组合多个状态变更
  • 调用其他 actions

与 Vuex 不同,Pinia 的 actions 同时支持同步和异步操作,无需区分 mutations/actions,简化了开发流程。

基本语法[编辑 | 编辑源代码]

Actions 在 store 定义中通过 actions 属性声明:

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  actions: {
    // 同步action
    increment() {
      this.count++
    },
    // 异步action
    async fetchData() {
      const response = await fetch('/api/data')
      this.data = await response.json()
    }
  }
})

关键特性[编辑 | 编辑源代码]

访问状态[编辑 | 编辑源代码]

在 action 内部通过 this 直接访问整个 store 实例:

actions: {
  doubleCount() {
    this.count *= 2 // 直接修改状态
  }
}

参数传递[编辑 | 编辑源代码]

Actions 可以接受任意数量的参数:

actions: {
  add(value) {
    this.count += value
  }
}

// 调用
store.add(5)

异步操作[编辑 | 编辑源代码]

Pinia 自动处理异步 actions 的 Promise 解析:

actions: {
  async fetchUser(id) {
    try {
      this.user = await api.fetchUser(id)
    } catch (error) {
      this.error = error
    }
  }
}

高级用法[编辑 | 编辑源代码]

组合 Actions[编辑 | 编辑源代码]

Actions 可以互相调用:

actions: {
  reset() {
    this.count = 0
  },
  async resetAndFetch() {
    this.reset() // 调用其他action
    await this.fetchData()
  }
}

订阅 Actions[编辑 | 编辑源代码]

可以通过 store.$onAction() 监听 action 调用:

const unsubscribe = store.$onAction(({ name, store, args, after, onError }) => {
  console.log(`Action "${name}" started`)
  
  after((result) => {
    console.log(`Action "${name}" completed`)
  })
  
  onError((error) => {
    console.error(`Action "${name}" failed:`, error)
  })
})

// 取消订阅
unsubscribe()

实际案例[编辑 | 编辑源代码]

购物车场景[编辑 | 编辑源代码]

sequenceDiagram participant Component participant Store participant API Component->>Store: addToCart(productId, quantity) Store->>API: POST /cart API-->>Store: Updated cart data Store->>Store: update cart state Store-->>Component: Updated cart

对应实现:

// cartStore.js
actions: {
  async addToCart(productId, quantity) {
    const currentItems = this.cartItems
    const existingItem = currentItems.find(item => item.id === productId)
    
    if (existingItem) {
      existingItem.quantity += quantity
    } else {
      currentItems.push({ id: productId, quantity })
    }
    
    try {
      await api.updateCart(currentItems)
      this.cartItems = currentItems
    } catch (error) {
      // 回滚变更
      this.cartItems = await api.getCart()
      throw error
    }
  }
}

用户认证流程[编辑 | 编辑源代码]

// authStore.js
actions: {
  async login(credentials) {
    this.loading = true
    try {
      const user = await authService.login(credentials)
      this.user = user
      this.isAuthenticated = true
      router.push('/dashboard')
    } catch (error) {
      this.error = error.message
    } finally {
      this.loading = false
    }
  }
}

最佳实践[编辑 | 编辑源代码]

1. 单一职责: 每个 action 应该只做一件事 2. 错误处理: 始终处理异步操作中的潜在错误 3. 可组合性: 将复杂操作拆分为多个小 actions 4. 命名约定: 使用动词命名 actions (如 fetchUser, updateSettings) 5. 避免直接修改参数: 对传入参数进行深拷贝(如需修改)

数学表示[编辑 | 编辑源代码]

Action 可以看作状态转换函数:

action:(State×Args)State×Result

其中:

  • State 是当前状态
  • Args 是输入参数
  • State 是新状态
  • Result 是 action 返回值

总结[编辑 | 编辑源代码]

Pinia Actions 提供了灵活的方式来组织业务逻辑,具有以下优势:

  • 统一处理同步/异步操作
  • 直接访问和修改状态
  • 支持 TypeScript 类型推断
  • 可组合和可订阅

通过合理使用 actions,可以使您的状态管理代码更加模块化和可维护。