vuex Mutations同步Actions異步原理解析

正文

vuex的mutationsactions有什麼區別,除瞭用法上mutation是同步,actions是異步,這裡的同步與異步指的是commitordispatch?並不是,同步指mutations方的內部是同步的,而actions內部可以是異步的,並且修改數據隻能在mutations中修改,在actions中異步的操作副作用是通過mutations來記錄。本文是一篇筆者記錄vuex關於mutationsactions的筆記。

避坑

如果使用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執行異步操作,將結果給瞭mutationsmutations中同步修改狀態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其它相關文章!

推薦閱讀: