Vue技术栈作为当今前端的核心技能之一,应该熟练掌握,不仅应该知其然,更应该知其所以然。以下部分为个人读vuex源码心得,主要分为三个部分,一个部分是从整体看其原理,一个是局部每个函数的实现过程分析,还有一部分是补充文档中未提及的部分
[toc]
整个存储体系是由module节点组成的一棵树,而 ModuleCollection则是这棵树的管理者 ,这是一个典型的组合模式。
当通过moduleCollection进行register,update,unRegister时,ModuleCollection是不进行具体的操作的,他只是把这些任务派发给具体的module,通过module自身的 addChild , update , removeChild进行实际的操作。此外,ModuleCollection还提供了对这棵树路径操作的办法,比如将从根节点到指定的子节点的路径以字符串的方式表达的getNamespace(path);比如根据指定路径获取module节点的 get( path ) 方法。
而每个module提供两部分功能,一类是操作自身,一类是管理子节点。操作自身的方法主要对应着module自身的_rawModule进行操作;管理子节点,主要对应着module的_children进行操作。
- 操作自身的有 : update , forEachGetter , forEachMutation , forEachAction。
- 管理子节点的有 : addChild , removeChild , getChild , forEachChild
当调用 new Vuex.Store( options ), 主要过程是:
-
通过 `this._modules = new ModuleCollection(options)` 构造这棵树。 -
通过 `installModule(this, state, [], this._modules.root)` 将这颗树的相关信息进行处理并存储到我们store实例的各个属性中,当对store实例的各种操作,实质上都是在用这棵树提供的信息功能进行相应的处理。
- applyMixin : 源码6~40行
- forEachValue : 源码87~91行
- isObject : 源码93~95行
- isPromise( val ) : 源码97~99行
- assert : 源码101~105行
- Module类 : 源码107~168
- ModuleCollection类 : 源码170~225行
- update : 源码227~254行
- assertRawModule : 源码256~292行
- makeAssertionMessage : 源码294~301行
- store构造函数 : 源码305~376行
- prototypeAccessors : 源码378~388行
- Store.prototype.commit : 源码390~425行
- Store.prototype.dispatch : 源码427~453行
- Store.prototype.subscribe : 源码455~457行
- Store.prototype.subscribeAction : 源码459~461行
- Store.prototype.watch 源码 : 463~472行
- Store.prototype.replaceState : 源码474~480行
- Store.prototype.registerModule : 源码482~498行
- Store.prototype.unregisterModule : 源码500~517行
- Store.prototype.hotUpdate : 源码519~522
- Store.prototype._withCommit : 源码524~531行
- genericSubscribe : 源码533~543行
- resetStore : 源码545~555行
- resetStoreVM : 源码557~607行
- installModule : 源码609~648行
- makeLocalContext : 源码650~713行
- makeLocalGetters : 源码715~740行
- registerMutation : 源码742~747行
- registerAction : 源码749~772行
- registerGetter : 源码774~789
- enableStrictMode : 源码791~799行
- getNestedState : 源码801~807行
- unifyObjectStyle : 源码809~821行
- install: 源码823~834行
- mapState : 源码836~861行
- mapMutations : 源码863~887行
- mapGetters : 源码889~910行
- mapActions : 源码912~936行
- createNamespacedHelpers : 源码938~945行
- normalizeMap : 源码947~955行
- normalizeNamespace : 源码957~965行
- getModuleByNamespace : 源码969~975行
当其第二个参数(第一个参数是namespace,可以没有)为对象时,该对象的键对应的值是函数时,除了获取namespace指定的state,还会获取对应的getters 源码中有:
return typeof val === 'function'
? val.call(this, state, getters)
: state[val]因此调用时可以:
mapState({
field : function( state , getters ){}
})当其第二个参数(第一个参数是namespace,可以没有)为对象时,该对象的键对应的值可以是函数,该函数第一个参数会是namespace指向的commit 源码中:
return typeof val === 'function'
? val.apply(this, [commit].concat(args))
: commit.apply(this.$store, [val].concat(args))因此调用时可以:
mapMutations({
field : function( commit , payload ){
//其他代码...
commit('type',payload);
//...
}
})当其第二个参数(第一个参数是namespace,可以没有)为对象时,该对象的键对应的值可以是函数,该函数第一个参数会是namespace指向的dispatch 源码中:
return typeof val === 'function'
? val.apply(this, [dispatch].concat(args))
: dispatch.apply(this.$store, [val].concat(args))因此调用时可以:
...mapActions({
asyncAdd( dispatch , payload){
dispatch('type',payload)
.then(function( data ){
console.log( '数据已经递交:' , data )
})
}
}) 国安信徒
2018-04-05