Actions如何定义的
恕小端不才,对Action的总结如下:
- Action 可以提交mutation方法,通过mutation来改变state
- Action 函数可以接收一个context对象,通过context.state 和 context.getters来改变state。(在实际工作中不常用)
- Action 可以执行任意的同步和异步操作
接下来我们通过上面三点总结来看Actions的使用:
Action 可以提交mutation方法,通过mutation来改变state
我们先在actions.js定义一个addCountAction方法用来做累加器
const actions = { addNumAction (context, num) { context.commit('addNum', num) }, addCountAction (context) { context.commit('add') } } export default actions
在组件中通过.dispatch进行分发Actions,内容如下:
<template> <div class="action"> <p>{{ count }}</p> <button @click="add">+ADD</button> </div> </template> <script> import { mapState } from 'vuex' export default { data () { return {} }, computed: { ...mapState(['count']) }, methods: { add () { this.$store.dispatch('addCountAction') } } } </script>
Action 函数可以接收一个context对象,通过context.state 和 context.getters来改变state。(不推荐使用)
在actions.js中定义一个新方法reduceCountAction方法,实现一个累减
const actions = { addNumAction (context, num) { context.commit('addNum', num) }, addCountAction (context) { context.commit('add') }, reduceCountAction (context) { context.state.count-- } } export default actions
在组件中通过.dispatch进行分发Actions,内容如下:
<template> <div class="action"> <button @click="reduce">-REDUCE</button> <p>{{ count }}</p> <button @click="add">+ADD</button> </div> </template> <script> import { mapState } from 'vuex' export default { data () { return {} }, computed: { ...mapState(['count']) }, methods: { add () { this.$store.dispatch('addCountAction') }, reduce () { this.$store.dispatch('reduceCountAction') } } } </script>
Action 可以执行任意的同步和异步操作
我们将actions.js中的addCountAction函数修改如下:
addCountAction (context) { setTimeout(function () { context.commit('add') }, 2000) }
修改后我们发现在执行累加的时候,会等待两秒才会执行。
在组件中使用mapActions 辅助函数
将之前的组件addCountAction函数用辅助函数替代,修改如下:
<template> <div class="action"> <button @click="reduce">-REDUCE</button> <p>{{ count }}</p> <button @click="addCountAction">+ADD</button> </div> </template> <script> import { mapState, mapActions } from 'vuex' export default { data () { return {} }, computed: { ...mapState(['count']) }, methods: { ...mapActions(['addCountAction']), reduce () { this.$store.dispatch('reduceCountAction') } } } </script>
组合Actions的使用
Action通常是异步的,那么如何知道action什么时候结束呢?更重要的是,我们如何才能组合多个action,以处理更加复杂的异步流程?
首先,你需要明白 store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise:
const actions = { addNumAction (context, num) { context.commit('addNum', num) }, addCountAction (context) { return new Promise((resolve, reject) => { setTimeout(() => { context.commit('add') resolve() }, 1000) }) }, reduceCountAction (context) { context.state.count-- }, addTwoAction (context) { context.dispatch('addCountAction').then(() => { context.commit('addTwo') }) } } export default actions
在上面我们在addTwoAction函数中实现了一个组合的actions
- 如果我们利用 async / await,我们可以如下组合 action
// 假设 getData() 和 getOtherData() 返回的是 Promise actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { await dispatch('actionA') // 等待 actionA 完成 commit('gotOtherData', await getOtherData()) } }
一个store.dispatch在不同模块中可以触发多个action函数。在这种情况下,只有当所有触发函数完成后,返回的Promise才会执行。
最后,我们说下官方的定义,在官网是这样定义的Actions:
- Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。