1.一个简单的用例
本文我们以一个Vuex的简单使用为例,探究Vuex的内部原理,首先上例子:
import Vuex from 'vuex'import Vue from 'vue'import {mapMutations,mapGetters} from 'vuex'Vue.use(Vuex)const state = { name:'Quino'}const mutations = { setName(state,payload){ state.name = payload }}const getters = { getName:state=>state.name}const store = new Vuex.Store{ state, mutations, getters}let vm = new Vue({ el, store, methods:{ ...mapMutations(['setName']) }, computed:{ ...mapGetters(['getName']) }})复制代码
先看一下mapMutations和mapGetters,这两个方法都来自src/helpers.js
export const mapMutations = normalizeNamespace((namespace, mutations) => { const res = {} normalizeMap(mutations).forEach(({ key, val }) => { res[key] = function mappedMutation (...args) { // Get the commit method from store let commit = this.$store.commit if (namespace) { const module = getModuleByNamespace(this.$store, 'mapMutations', namespace) if (!module) { return } commit = module.context.commit } return typeof val === 'function' ? val.apply(this, [commit].concat(args)) : commit.apply(this.$store, [val].concat(args)) } }) return res})复制代码
其中normalizeNamespace定义在文件最下方,用于处理命名空间,由于我们没有使用命名空间,所以相当于直接用normalizeNamespace内的匿名函数参数直接处理我们的数组参数,此时namespace='',mutations=['setName']。
然后normalizeMap将mutations处理成[{key:'setName',val:'setName'}],normalizeMap目的是将我们的参数规范化,由其源码可知mapMutations的参数除了可以是数组外,还可以是对象,如下:
mapMutations({ setName:(commit,payload)=>{ commit('setName',payload) }])复制代码
之后就按照mutations给局部变量res添加属性,最后返回了res,所以,我们上面的例子中,vm会得到一个这样的methods:
methods:{ setName:function mappedMutation(){ this.$store.commit('setName',payload); }}复制代码
是不是和我们写的是一样的呢,只不过Vuex帮我们封装了这一步,使我们用起来更方便,可以像vm.setName('quino')
这样直接使用,Vuex已经帮我们将内部的this绑定成了store。
同理,mapGetters会被处理成这样:
cmputed:{ getName:()={ return this.$store.getters['getName'] }}复制代码
同时getName的函数上还有一个vuex属性设置为true,用于和其他计算属性区分。
还记得前面总结的store的结构吗,这里的this.$store.getters其实会访问store._vm的computed属性。
2.操作store
这时如果我们调用vm.setName('www')会发生什么呢?
- 首先会修改store内部的state属性
- 因为这个属性被store内部的_vm的data属性引用,所以会触发响应式,使得_vm的计算属性重新计算。
- 由于this.$store.getters访问的是_vm.computed,所以这也会触发我们例子中的实例vm的计算属性发生变化。
- 由此,一个状态变化的侦测就完成了。
总结:Vuex还是利用了Vue响应式的特点来进行状态管理,在其内部定义了一个_vm用以管理我们的state。
后记:Vuex的源码探秘就到这里吧,对于Vuex的实现原理也掌握了个大概,但很多细节并没有去深究,以后需要的时候再回过头看看。