一开始用vuex的时候我也十分疑惑,然后百度一下发现官网和大部分博客都说的是一个支持同步操作一个支持异步操作,最近开始看源码发现其实不完全是这么回事,先看源码吧,这里使用的node_modules下的vuex.esm.js。
mutations是通过commit触发的,看看commit的源码
这段代码大致干了什么,参数type就是你定义的事件类型,在简单的vuex中就是一个代表事件名的字符串(type:'xxxx'),unifyObjectStyle函数的作用是如果第一个参数type是对象并且有其中有type字段(type:{type:xxx})就会把第二个参数赋给第三个参数,第一个参数赋给第二个参数,然后第一个参数取自身的.type属性。
这里的this._mutations其实就是你在vuex中配置的mutations,entry是一个函数数组,里面装的就是你mutations对应type的回调函数。
this._withCommit的意义是在其中定义了一个commiting的变量,赋值为this._committing(初始值为false),在你entry.forEach遍历回调的时候,会简单的控制_commiting的值,改变store中的变量,加这么一层的意义是在于你使用严格模式的时候,直接操作this.$store.state中值的时候,会抛出 do not mutate vuex store state outside mutation handlers 的异常(所以这里其实暴露了,为啥能直接修改变量,还会有getting这个配置)。
最后是this._subscribers,其实你看到这里,并没有任何一个地方限制commit的异步操作,其实他也确实没有限制,问题就出在this._subscribers中,这个是devtool的控件,this._subscribers本身是一个函数数组,里面装的是参数为mutation和state的函数,函数大致内容为:devtoolHook.emit('vuex:mutation', mutation, state),作用是在每次commit执行完mutations中回调的时候,控制浏览器插件进行跟踪,如果你浏览器没有Vue的插件,devtool是一个undefined,所以这里也没什么意义。如果你在mutation中使用了异步操作,devtool的钩子会先于mutations回调执行,导致无法捕捉store的变化。
所以如果你本身不使用浏览器进行调试的时候,mutations里是可以包含异步操作的,只是影响使用插件来定位bug,至少我现在还没有遇到什么bug,如果有问题也欢迎大家指正。最后对比一下dispath的源码。
熟悉的Promise熟悉的味道,其实作用就只是把commit里,devtool和mutations的回调同步处理了而已,便于程序猿们通过浏览器插件定位bug。
最直观的例子就是,你通过vuex定义一个全局的累加器,在mutations里写个setTimeout5000ms的count++,在actions里也写了一个,你打开浏览器的vue插件,瞬间点击10次累加,你使用commit触发事件时,右侧调适会直接出现10个状态,然后累加器的状态都是0(最后页面会没有问题的变成10)。你用dispatch触发,那就是在5000s延迟后出现正常的1~10的累加器状态(最后页面上也还是10,没啥区别)。
网友评论