详解vuex之store源码简单解析
关于vuex的基础部分学习于https://www.nhooo.com/article/163008.htm
使用Vuex的时候,通常会实例化Store类,然后传入一个对象,包括我们定义好的actions、getters、mutations、state等。store的构造函数:
exportclassStore{ constructor(options={}){ //若window内不存在vue,则重新定义Vue if(!Vue&&typeofwindow!=='undefined'&&window.Vue){ install(window.Vue) } if(process.env.NODE_ENV!=='production'){ //断言函数,来判断是否满足一些条件 //确保Vue的存在 assert(Vue,`mustcallVue.use(Vuex)beforecreatingastoreinstance.`) //确保Promsie可以使用 assert(typeofPromise!=='undefined',`vuexrequiresaPromisepolyfillinthisbrowser.`) assert(thisinstanceofStore,`storemustbecalledwiththenewoperator.`) } //解构赋值,拿到options里的plugins和strict const{ plugins=[], strict=false }=options //创建内部属性 //标志一个提交状态,作用是保证对Vuex中state的修改只能在mutation的回调函数中,而不能在外部随意修改state this._committing=false //用来存储用户定义的所有的actions this._actions=Object.create(null) this._actionSubscribers=[] //用来存储用户定义所有的mutatins this._mutations=Object.create(null) //用来存储用户定义的所有getters this._wrappedGetters=Object.create(null) //用来存储所有的运行时的modules this._modules=newModuleCollection(options) this._modulesNamespaceMap=Object.create(null) //用来存储所有对mutation变化的订阅者 this._subscribers=[] //一个Vue对象的实例,主要是利用Vue实例方法$watch来观测变化的 this._watcherVM=newVue() //把Store类的dispatch和commit的方法的this指针指向当前store的实例上 conststore=this const{dispatch,commit}=this this.dispatch=functionboundDispatch(type,payload){ returndispatch.call(store,type,payload) } this.commit=functionboundCommit(type,payload,options){ returncommit.call(store,type,payload,options) } //是否开启严格模式 this.strict=strict conststate=this._modules.root.state //Vuex的初始化的核心,其中,installModule方法是把我们通过options传入的各种属性模块注册和安装; //resetStoreVM方法是初始化store._vm,观测state和getters的变化;最后是应用传入的插件。 installModule(this,state,[],this._modules.root) resetStoreVM(this,state) plugins.forEach(plugin=>plugin(this)) constuseDevtools=options.devtools!==undefined?options.devtools:Vue.config.devtools if(useDevtools){ devtoolPlugin(this) } }
Vuex本身是单一状态树,应用的所有状态都包含在一个大对象内,随着我们应用规模的不断增长,这个Store变得非常臃肿。为了解决这个问题,Vuex允许我们把store分模块。每一个模块包含各自的state、mutations、actions和getters,甚至还可以嵌套模块。
接下来看installModule方法:
functioninstallModule(store,rootState,path,module,hot){ //通过path数组的长度判断是否为根 constisRoot=!path.length constnamespace=store._modules.getNamespace(path) //registerinnamespacemap if(module.namespaced){ store._modulesNamespaceMap[namespace]=module } //第一次调用时,path为空,不进入if //递归调用installModule安装子模块时,将执行该代码块 if(!isRoot&&!hot){ constparentState=getNestedState(rootState,path.slice(0,-1)) //模块名 constmoduleName=path[path.length-1] //把当前模块的state添加到parentState中。具体解析见下 store._withCommit(()=>{ Vue.set(parentState,moduleName,module.state) }) } constlocal=module.context=makeLocalContext(store,namespace,path) //对mutations、actions、getters进行注册 module.forEachMutation((mutation,key)=>{ constnamespacedType=namespace+key registerMutation(store,namespacedType,mutation,local) }) module.forEachAction((action,key)=>{ consttype=action.root?key:namespace+key consthandler=action.handler||action registerAction(store,type,handler,local) }) module.forEachGetter((getter,key)=>{ constnamespacedType=namespace+key registerGetter(store,namespacedType,getter,local) }) //遍历modules,递归调用installModule安装子模块 module.forEachChild((child,key)=>{ installModule(store,rootState,path.concat(key),child,hot) }) } store的_withCommit方法定义是这样的: _withCommit(fn){ constcommitting=this._committing this._committing=true fn() this._committing=committing }
Vuex中所有对state的修改都会用_withCommit函数包装,保证在同步修改state的过程中this._committing的值始终为true。这样当我们观测state的变化时,如果this._committing的值不为true,则能检查到这个状态修改是有问题的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。