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 可以包含任意異步操作。