Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
  • mutation 是同步事务

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.statecontext.getters 来获取 state 和 getters。当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了。

<!DOCTYPE html>
<html lang="en" xmlns="">
<head>
    <meta charset="UTF-8">
    <title>Vuex:actions 的使用</title>
</head>
<body>
<div id="app">
    <button-counter></button-counter>
</div>

<script src="vuex.js"></script>
<script src="vue.js"></script>
<script>
  Vue.component('ButtonCounter', {
    computed: {
      ...Vuex.mapState([
        'count'
      ])
    },
    methods: {
      increment() {
        // 使用 dispatch 触发 actions 下的方法
        this.$store.dispatch('increment')
      },
      ...Vuex.mapActions([
        // 将 `this.incrementAsync(timeout)` 映射为 `this.$store.dispatch('incrementAsync', timeout)`
        'incrementAsync'
      ]),
      ...Vuex.mapActions({
        // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
        add: 'increment'
      })
    },
    template: `
      <div>
      <button @click="increment">increment:You clicked me {{ count }} times.</button><hr>
      <button @click="incrementAsync(1000)">incrementAsync:You clicked me {{ count }} times.</button>
      </div>
    `
  })

  // 创建Vuex容器
  const store = new Vuex.Store({
    state: {
      count: 0
    },
    mutations: {
      increment(state) {
        state.count++
      }
    },
    // 异步操作
    actions: {
      // increment(context) {
      //   context.commit('increment')
      // },
      // ES6 简化写法,以上面作用相同
      increment({commit}) {
        commit('increment')
      },
      // 带有载荷 timeout,载荷可以是 对象,使用方法与 mutations 相同
      incrementAsync({commit}, timeout) {
        setTimeout(() => {
          commit('increment')
        }, timeout)
      }
    }
  })

  new Vue({
    el: '#app',
    store
  });

</script>
</body>
</html>

复杂一点的例子:

store.js:单独配置 Vuex 容器

import Vue from 'vue'
import Vuex from 'vuex'
import {types} from './mutation-types'
import shop from './shop'

Vue.use(Vuex)

// 创建Vuex容器
export default new Vuex.Store({
  state: {
    cart: {
      added: [] // 购物车添加的物品列表
    }
  },
  mutations: {
    [types.CHECKOUT_REQUEST](state) {
      console.log('清空购物车 ' + state)
    },
    [types.CHECKOUT_SUCCESS](state) {
      console.log('购物成功时调用 ' + state)
    },
    [types.CHECKOUT_FAILURE](state, savedCartItems) {
      console.log('购物失败时调用 ' + state)
      console.log(savedCartItems)
    },
  },
  // 异步操作
  actions: {
    checkout({commit, state}, products) {
      // 把当前购物车的物品备份起来
      const savedCartItems = [...state.cart.added]
      // 发出结账请求,然后乐观地清空购物车
      commit(types.CHECKOUT_REQUEST)
      // 购物 API 接受一个成功回调和一个失败回调
      setTimeout(() => {
        shop.buyProducts(
          products, // 购买的产品
          // 成功操作
          () => commit(types.CHECKOUT_SUCCESS),
          // 失败操作
          () => commit(types.CHECKOUT_FAILURE, savedCartItems)
        )
      }, 2000)
    }
  }
})

mutation-types.js:mutations 方法名称统一管理,有助于项目团队对 state 所包含的 mutations 一目了然

export const types = {
  CHECKOUT_REQUEST: 'checkoutRequest',
  CHECKOUT_SUCCESS: 'checkoutSuccess',
  CHECKOUT_FAILURE: 'checkoutFailure',
}

shop:购物类的定义文件

export default function shop() {
  // 购买商品 API
  this.buyProducts = function (products, success, failure) {
    console.log(products) // 购买的产品
    console.log(success) // 操作成功时调用
    console.log(failure) // 操作失败时调用
  };
}

调用其他异步方法:

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  },
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  },
}

配合 async/await 使用:

// 假设 getData() 和 getOtherData() 返回的是 Promise

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

前往低代码交流专区

更多推荐