Vuex@next源码解析 - module篇
前言
本篇主要写Vuex
中模块最基本的的一个单位,Module
– 模块对象
module.js
1 | export default class Module { |
不用因为这么多方法感到退却,因为其实这些方法都是一些非常简单的方法,放下心往👇看就完事~
constructor
构造器函数addChild
添加一个子模块Module
对象removeChild
移除一个子模块Module
对象getChild
得到一个子模块Module
对象hasChild
是否拥有一个子模块Module
对象update
更新本模块forEachChild
遍历每一个子模块forEachGetter
遍历本模块每一个getter
forEachAction
遍历本模块每一个action
forEachMutation
遍历本模块每一个mutation
看起来很多,其实对于xxxChild
这几个方法,颇有点增删改查的味道😂
后四个forEachXXX
函数很明显为遍历函数
constructor
1 | // Base data struct for store's module, package with some attribute and method |
构造器函数表明了将会往对象上挂载什么属性
this.runtime
表示是否是运行时注册的模块,前面说到的注册根root
模块时
在ModuleCollection
的构造器中执行了this.register([], rawRootModule, false)
这里第三个参数为false
也就表明了根模块是不可以卸载的
this._children
本模块包含的子Module
对象
this._rawModule
用于创建模块的参数(就是用于传进来的options
),比如现在有如下store
1 | const store = createStore({ |
那么对于根root
和m1
,他们的_rawModule
,应该是这个传入的配置对象什么部分?
可能有人会认为都是整个配置对象,但其实不是,因为在ModuleCollection
类中的register
方法中
1 | // register nested modules |
这里通过工具函数forEachValue
来来遍历传入的配置参数的modules
(如果存在的情况下),每次回调的rawChildModule
为本模块的一个配置对象
比如此时遍历到了modules
下的m1
,此时两者分别为
1 | rawChildModule = { |
那么对于m1
,他的_rawModule
和rawChildModule
一样,就为
1 | _rawModule = { |
而对于根root
模块,他的_rawModule
,就是整个传进来的参数对象
1 | _rawModule = { |
我们可以在控制台展开看看
发现基本符合预期,但是根root
模块的state
是合并的,在这个文件中并没有相关的操作,哪又是在进行合并的呢?
没错,之前store
篇说过,是store.js
文件中的installModule
方法
在Store
类的构造器函数中,调用了installModule
,如下
1 | const state = this._modules.root.state |
然后在installModule
中,有一段判断
1 | // set state |
此时的rootState
就是this._modules.root.state
也就是非根模块的时候,通过getNestedState
取到父模块,然后把当前模块的state
挂载到父模块的state
上
this.state
也就是本模块的状态,通过_rawModule.state
来获取
这里做了个判断,也就是我们传入的state
属性不一定是要一个对象,也可以是一个函数返回一个对象
addChild
1 | export default class Module { |
非常简单,我觉得初学者都能看懂🤣,就是往_children
属性上挂载上传入的Module
对象而已
removeChild
1 | export default class Module { |
通过delete
删除对应key
的Module
对象
getChild
1 | export default class Module { |
通过_children
属性返回对应的Module
对象
hasModule
1 | export default class Module { |
通过in
操作符号判断模块名key
是否存在_children
属性中
update
1 | export default class Module { |
通过传入的rawModule
配置来更新本模块的_rawModule
可以看到,覆盖了namespaced
,getters
,mutations
,actions
但是没有覆盖state
!,没有覆盖state
!!,没有覆盖state
!!!
重要的话讲三遍好吧,这个API可以追溯到store.hotUpdate
这个方法上,热更新时用到,可以不用太在意
forEachXXX
1 | export default class Module { |
这四个函数非常简单,依赖了工具函数forEachValue
,
每个函数对特定的对象进行属性以及对应值的遍历
后记
这个文件写完基本上核心代码就写完了
接下来会整体改进这几篇文章的细节,使大家更容易懂