跳转到内容

Vuex Actions

来自代码酷

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

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

Vuex Actions 是 Vuex 状态管理库中用于处理异步操作和复杂业务逻辑的核心机制。与 mutations 不同,actions 不直接修改状态,而是通过提交 mutations 来间接修改状态。这使得 actions 非常适合处理 API 请求、定时任务或其他异步操作。

Actions 的特点:

  • 可以包含任意异步操作(如 API 调用)
  • 通过 commit 方法触发 mutations
  • 通过 dispatch 方法调用其他 actions
  • 接收一个与 store 实例具有相同属性和方法的 context 对象

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

以下是一个简单的 action 定义:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    incrementAsync (context) {
      setTimeout(() => {
        context.commit('increment')
      }, 1000)
    }
  }
})

调用 action 的方式:

// 在组件中
this.$store.dispatch('incrementAsync')

// 使用 mapActions 辅助函数
import { mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions(['incrementAsync'])
  }
}

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

Actions 可以接受额外参数(payload):

actions: {
  addTodo (context, todoText) {
    // 模拟 API 调用
    api.addTodo(todoText).then(() => {
      context.commit('addTodo', todoText)
    })
  }
}

// 调用时传递参数
this.$store.dispatch('addTodo', 'Learn Vuex actions')

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

Actions 可以返回 Promise,使得它们可以方便地组合:

actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}

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

用户登录流程[编辑 | 编辑源代码]

以下是一个完整的用户登录 action 示例:

actions: {
  async login({ commit }, credentials) {
    try {
      commit('setLoading', true)
      const response = await authApi.login(credentials)
      commit('setUser', response.data.user)
      commit('setToken', response.data.token)
      commit('setLoading', false)
      router.push('/dashboard')
    } catch (error) {
      commit('setError', error.message)
      commit('setLoading', false)
    }
  }
}

购物车操作[编辑 | 编辑源代码]

处理购物车商品添加的复杂逻辑:

actions: {
  addToCart({ state, commit, dispatch }, product) {
    // 检查库存
    if (product.inventory <= 0) {
      return dispatch('showNotification', 'Product out of stock')
    }
    
    // 检查是否已存在
    const cartItem = state.cart.find(item => item.id === product.id)
    if (cartItem) {
      commit('incrementItemQuantity', cartItem)
    } else {
      commit('pushItemToCart', { ...product, quantity: 1 })
    }
    
    // 更新库存
    commit('products/decrementInventory', product.id, { root: true })
  }
}

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

1. 保持 actions 精简:将复杂逻辑拆分为多个 actions 2. 处理错误:始终捕获并处理异步操作中的错误 3. 命名空间:在大型应用中使用模块和命名空间 4. 可测试性:设计易于测试的 actions

常见问题[编辑 | 编辑源代码]

Actions 和 Mutations 的区别[编辑 | 编辑源代码]

特性 Actions Mutations
同步/异步 可以包含异步操作 必须是同步的
调用方式 dispatch commit
状态修改 不直接修改状态 直接修改状态

何时使用 Actions[编辑 | 编辑源代码]

  • 需要与后端 API 通信时
  • 需要执行多个 mutations 时
  • 需要处理复杂业务逻辑时
  • 需要执行异步操作时

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

模块中的 Actions[编辑 | 编辑源代码]

在模块中,局部 actions 的 context 对象会暴露根状态:

modules: {
  user: {
    actions: {
      login({ commit, dispatch, rootState }) {
        // 可以访问 rootState
        if (rootState.maintenanceMode) {
          return dispatch('showMaintenanceMessage')
        }
        // 正常登录逻辑
      }
    }
  }
}
</script>

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

可以使用 store.subscribeAction 监听 actions:

store.subscribeAction((action, state) => {
  console.log(`Action ${action.type} with payload:`, action.payload)
})

可视化流程[编辑 | 编辑源代码]

sequenceDiagram participant Component participant Action participant Mutation participant State Component->>Action: dispatch('actionName') Action->>Mutation: commit('mutationName') Mutation->>State: Modify state State-->>Component: Trigger re-render

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

在复杂状态转换中,可以用数学表示 action 的纯函数特性:

f(context,payload)Promise|void

其中:

  • context 包含 store 方法和属性
  • payload 是传入的数据
  • 返回 Promise 或 undefined