Action
 
 
 
  
1. 前言
 
 
 
  本小节我们将介绍如何使用 Action。包括如何定义 Action、分发 Action、mapActions 辅助函数的使用方式。Action 在 Vuex 中会大量使用,学好如何使用 Action 非常重要。Action 并不是一个难点,它的使用非常简单,接下来我们就一步步学习它的使用。
 
  
 
  
2. Action 简介
 
 
 
  Action 类似于 Mutation,不同的是:
 
  
 
   
   -  
     
     - Action 提交的是 mutation,而不是直接变更状态。
 
-  
     
     - Action 可以包含任意异步操作。在 vuex的使用过程中,我们可以将多个Mutation合并到一个Action中,也可以通过Action进行异步操作。
 
 
 
  
3. 基础用法
 
 
 
  
3.1 定义 action
 
 
 
  Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
 
  
 
  const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    
    increment (context) {
      context.commit('increment')
    },
    
    incrementAsync (context) {
      setTimeout(() => {
        context.commit('increment')
      }, 1000)
    }
  }
})
 
  
 
  实践中,我们会经常用到 ES2015 的参数解构来简化代码(特别是我们需要调用 commit 很多次的时候):
 
  
 
  actions: {
  increment ({ commit }) {
    commit('increment')
  }
}
 
  
 
  
3.2 分发 Action
 
 
 
  Action 通过 store.dispatch 方法触发:
 
  
 
  store.dispatch('increment')
 
  
 
  
3.3 提交载荷(Payload)
 
 
 
  你可以向 store.dispatch 传入额外的参数,即 Actions 的 载荷(payload):
 
  
 
  action: {
  increment ({commit}, payload) {
    
  }
}
 
  
 
  store.dispatch('increment', {count: 10})
 
  
 
  
3.4 对象风格的提交方式
 
 
 
  提交 action 的另一种方式是直接使用包含 type 属性的对象:
 
  
 
  store.dispatch({
  type: 'increment',
  count: 10
})
 
  
 
  当使用对象风格的提交方式,整个对象都作为载荷传给 action 函数,因此 handler 保持不变:
 
  
 
  actions: {
  increment ({commit}, payload) {
    
  }
}
 
  
 
  
 
  
 
 
 
  代码解释
 JS 代码第 9-11 行,我们定义了 mutation 事件 increment,事件对 state.count + 1。
 JS 代码第 15-17 行,我们定义了同步 Action increment,Action 中直接提交事件 increment。
 JS 代码第 18-22 行,我们定义了异步 Action incrementAsync,1 秒后提交事件 increment。
 JS 代码第 23-27 行,我们定义了接收参数的异步 Action incrementAsyncParams。
 JS 代码第 35 行,分发 Action 事件 increment。
 JS 代码第 38-40 行,以对象的形式分发 Action 事件 incrementAsync。
 JS 代码第 43-45 行,分发 Action 事件 incrementAsyncParams,并传入对应参数。
 
  
 
  
4 mapActions 辅助函数
 
 
 
  mapActions 辅助函数帮助我们简化提交 action 的写法。
 
  
 
  
4.1 mapActions 接收数组格式的参数
 
 
 
  mapActions 可以接收一个 action 事件名的数组:
 
  
 
  ...mapActions([
  
  'increment'
]),
 
  
 
  
4.2 mapActions 接收对象格式的参数
 
 
 
  在某些情况,我们需要对 Action 中的函数名重命名以避免和组件内部的变量冲突,这时候我们可以使用对象的方式接收参数:
 
  
 
  ...mapActions({
  [别名]: [Action name] 
})
...mapActions({
  add: 'increment'
})
 
  
 
  
 
  
 
 
 
  代码解释
 JS 代码第 23-25 行,我们通过 mapActions 将 this.increment () 映射为 this.$store.dispatch (‘increment’)。
 JS 代码第 26-28 行,我们通过 mapActions 将 this.add () 映射为 this.$store.dispatch (‘increment’)。
 
  
 
  
5. 组合 Action
 
 
 
  Action 通常是异步的,有时候我们需要知道 action 什么时候结束,并在结束后进行相应的其他操作。更重要的是,我们可以组合多个 action,以处理更加复杂的异步流程。
 首先,你需要明白 store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise:
 
  
 
  actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}
 
  
 
 
  store.dispatch('actionA').then(() => {
  
})
 
  
 
 
  actions: {
  
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}
 
  
 
  最后,如果我们利用 async /await,我们可以如下组合 action:
 
  
 
  
actions: {
  async actionA ({ commit }) {
    commit('increment', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') 
    commit('increment', await getOtherData())
  }
}
 
  
 
  
 
  
 
 
 
  代码解释
 JS 代码第 4-19 行,我们定义函数 getData 和 getOtherData。
 JS 代码第 29-31 行,定义 actionA,当 getData 函数执行完成之后 commit increment 事件。
 JS 代码第 32-35 行,定义 actionB,当 dispatch (actionA) 执行完成之后 commit increment 事件。
 
  
 
  
6. 小结
 
 
 
  本小节我们介绍了如何使用 Action 来操作 mutation 或者进行异步操作。主要知识点有以下几点:
 
  
 
   
   - 在 store 中定义 Action 事件。
- 通过 $store.dispatch 分发 Action 事件。
- 通过 Action 处理异步操作、合并处理 Mutation。
- 使用 mapActions 方法简化分发 Action 的写法。