? ? ? ?一開始用vuex的時候我也十分疑惑,然后百度一下發(fā)現(xiàn)官網(wǎng)和大部分博客都說的是一個支持同步操作一個支持異步操作,最近開始看源碼發(fā)現(xiàn)其實不完全是這么回事唁毒,先看源碼吧,這里使用的node_modules下的vuex.esm.js星爪。
? ? ? ?mutations是通過commit觸發(fā)的浆西,看看commit的源碼
? ? ? ?這段代碼大致干了什么,參數(shù)type就是你定義的事件類型移必,在簡單的vuex中就是一個代表事件名的字符串(type:'xxxx')室谚,unifyObjectStyle函數(shù)的作用是如果第一個參數(shù)type是對象并且有其中有type字段(type:{type:xxx})就會把第二個參數(shù)賦給第三個參數(shù),第一個參數(shù)賦給第二個參數(shù)崔泵,然后第一個參數(shù)取自身的.type屬性秒赤。
? ? ? ?這里的this._mutations其實就是你在vuex中配置的mutations,entry是一個函數(shù)數(shù)組憎瘸,里面裝的就是你mutations對應(yīng)type的回調(diào)函數(shù)入篮。
? ? ? ?this._withCommit的意義是在其中定義了一個commiting的變量,賦值為this._committing(初始值為false)幌甘,在你entry.forEach遍歷回調(diào)的時候潮售,會簡單的控制_commiting的值痊项,改變store中的變量,加這么一層的意義是在于你使用嚴(yán)格模式的時候酥诽,直接操作this.$store.state中值的時候鞍泉,會拋出 do not mutate vuex store state outside mutation handlers 的異常(所以這里其實暴露了,為啥能直接修改變量肮帐,還會有g(shù)etting這個配置)咖驮。
? ? ? ?最后是this._subscribers,其實你看到這里训枢,并沒有任何一個地方限制commit的異步操作托修,其實他也確實沒有限制,問題就出在this._subscribers中恒界,這個是devtool的控件睦刃,this._subscribers本身是一個函數(shù)數(shù)組,里面裝的是參數(shù)為mutation和state的函數(shù)十酣,函數(shù)大致內(nèi)容為:devtoolHook.emit('vuex:mutation', mutation, state)涩拙,作用是在每次commit執(zhí)行完mutations中回調(diào)的時候,控制瀏覽器插件進(jìn)行跟蹤婆誓,如果你瀏覽器沒有Vue的插件吃环,devtool是一個undefined也颤,所以這里也沒什么意義洋幻。如果你在mutation中使用了異步操作,devtool的鉤子會先于mutations回調(diào)執(zhí)行翅娶,導(dǎo)致無法捕捉store的變化文留。
? ? ? ? 所以如果你本身不使用瀏覽器進(jìn)行調(diào)試的時候,mutations里是可以包含異步操作的竭沫,只是影響使用插件來定位bug燥翅,至少我現(xiàn)在還沒有遇到什么bug,如果有問題也歡迎大家指正蜕提。最后對比一下dispath的源碼森书。
熟悉的Promise熟悉的味道,其實作用就只是把commit里谎势,devtool和mutations的回調(diào)同步處理了而已凛膏,便于程序猿們通過瀏覽器插件定位bug。
? ? ? ? 最直觀的例子就是脏榆,你通過vuex定義一個全局的累加器猖毫,在mutations里寫個setTimeout5000ms的count++,在actions里也寫了一個须喂,你打開瀏覽器的vue插件吁断,瞬間點擊10次累加趁蕊,你使用commit觸發(fā)事件時,右側(cè)調(diào)適會直接出現(xiàn)10個狀態(tài)仔役,然后累加器的狀態(tài)都是0(最后頁面會沒有問題的變成10)掷伙。你用dispatch觸發(fā),那就是在5000s延遲后出現(xiàn)正常的1~10的累加器狀態(tài)(最后頁面上也還是10又兵,沒啥區(qū)別)炎咖。