详解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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。