首頁 > 軟體

vuex Mutations同步Actions非同步原理解析

2022-12-11 14:01:01

正文

vuexmutationsactions有什麼區別,除了用法上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的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com