vuex Mutations同步Actions異步原理解析
正文
vuex的mutations
與actions
有什麼區別,除瞭用法上mutation
是同步,actions
是異步,這裡的同步與異步指的是commit
ordispatch
?並不是,同步指mutations
方的內部是同步的,而actions
內部可以是異步的,並且修改數據隻能在mutations
中修改,在actions
中異步的操作副作用是通過mutations
來記錄。本文是一篇筆者記錄vuex
關於mutations
與actions
的筆記。
避坑
如果使用vue-cli2
模版搭建的基礎項目,註意,如果使用vue
版本是2,當你你默認安裝vuex
肯定是4.x
版本瞭,這裡需要註意的是,你要降低vuex
版本到3.x
版本,不然store
掛載不到vue
上
mutation
當我們修改數據,隻能通過mutation
修改state
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({ state: { data: [] }, mutations: { storeData (state, payload) { state.data = state.data.concat(payload) } } })
在頁面中
import { mockFeatchData } from '@/mock' export default { name: 'HelloWorld', data () { return { msg: 'Welcome to Your Vue.js App' } }, computed: { ...mapState({ dataList: state => state.data }) }, methods: { handleData () { mockFeatchData().then(res => { this.$store.commit('storeData', res) }) } } }
我們修改數據就是$store.commit('eventName', payload)
,當我們觸發commit
時,實際上是已經在異步請求回調裡獲取瞭數據。
但是官方在描述mutation
有這麼說,mutation
內部必須是同步函數,異步會導致內部狀態難以追蹤,devtool
難以追蹤state
的狀態
... mutations: { storeData (state, payload) { mockFeatchData().then((res) => { console.log(res) state.data = state.data.concat(res) }) } },
也就是說上面這段代碼,當我們在mutations
中的storeData
中使用瞭異步函數,我們在$store.commit('storeData')
時,很難追蹤state
的狀態,因為在觸發commit事件時,異步的回調函數不知道什麼時候執行,所以難以追蹤。
mutations
是同步事務,假設在mutations
有多個異步的調用,你很難確定這些異步哪些先執行,很難追蹤state
的變化,所以也給調試帶來瞭一定難度
話說回來,這麼寫也確實是可以做到更新state的值,如果我不用vuetool
這個工具,貌似也沒毛病
既然mutations
是同步的事情,那麼異步官方就使用瞭actions
方案
actions
actions
裡面可以做異步操作,但是並不是直接修改數據,提交的是mutations
裡面的方法
mutations: { storeData (state, payload) { state.data = state.data.concat(payload) } }, actions: { setStoreData ({ commit }) { mockFeatchData().then((res) => { commit('storeData', res) }) } }
在頁面中就是這樣觸發actions
的
methods: { handleData () { this.$store.dispatch('setStoreData') } }
我們把異步操作放在瞭actions
的方法裡面,你會發現mockFeatchData
這是一個異步操作後的結果,然後通過commit
傳給瞭mutations
中
在actions
執行異步操作,將結果給瞭mutations
,mutations
中同步修改狀態state
,使得actions
的操作在mutations
中有記錄。
在actions
中也可以有多個異步操作
mutations: { storeData (state, payload) { state.data = state.data.concat(payload) }, storeText (state, payload) { state.text = payload } }, actions: { setStoreData ({ commit }) { mockFeatchData().then((res) => { console.log(res, '111') commit('storeData', res) }) }, setStoreText ({ dispatch, commit }, payload) { dispatch('setStoreData').then(() => { console.log(222) commit('storeText', payload) }) } }
頁面上是這樣觸發actions
的
handleText () { this.$store.dispatch('setStoreText', `hello,${Math.random()}`) }
這裡我們也可以用對象的方式
handleText () { this.$store.dispatch({ type: 'setStoreText', payload: `hello,${Math.random()}` })
不過此時註意actions
中獲取值需要解構才行
setStoreText ({ dispatch, commit }, {payload}) { dispatch('setStoreData').then(() => { console.log(222, payload) commit('storeText', payload) }) }
在actions可以dispatch
另一個異步的操作,也就是等一個任務完成瞭後,可以執行另一個commit
看到這裡貌似這裡有點明白,為啥所有的異步操作放在actions
裡面瞭,mutation
隻負責修改state
,所有異步操作產生的副作用的結果都統統交給瞭mutation
,這樣很好保證devtool
瞭對數據的追蹤。
總結
靈魂拷問,為什麼會有actions
中是異步,而mutations
是同步,從官方解釋來看,修改state數據必須隻能mutations
中修改,而假設mutions
內部有異步,那麼會帶來devtool
無法準確追蹤state
變化,因為多個異步並不知道哪個異步會先執行完。但是話說回來,mutations
中有異步,依然可以修改state啊,因為業務中我並不太需要知道devtool
是如何追蹤state
的變化,但是為瞭遵從規范,所有的異步都在actions
中處理,mutations
隻集中幹一件事,直接修改state
值
actions
是異步操作的,actions
中可以有多個異步操作,但是最終的結果依然是交給mutations
去修改的,也就是說actions
中異步操作的副作用統一交給瞭mutations
去記錄
多個異步任務可以在actions
中觸發,dispatch('xxx')
返回的是一個Promise
本文code example
以上就是vuex Mutations同步Actions異步原理解析的詳細內容,更多關於vuex Mutations Actions的資料請關註WalkonNet其它相關文章!