vuex 模块初始化源码阅读

  • Post author:
  • Post category:vue


GitHub:

https://github.com/vuejs/vuex/blob/dev/src/module/module-collection.js

首先看构造函数:

constructor (rawRootModule) {
    // register root module (Vuex.Store options)
    this.register([], rawRootModule, false)
  }

只是执行了一下register这个函数。借着看看这个函数做了什么

register (path, rawModule, runtime = true) {
    if (process.env.NODE_ENV !== 'production') {
      assertRawModule(path, rawModule)
    }

    const newModule = new Module(rawModule, runtime)
    if (path.length === 0) {
      this.root = newModule
    } else {
      const parent = this.get(path.slice(0, -1))
      parent.addChild(path[path.length - 1], newModule)
    }

    // register nested modules
    if (rawModule.modules) {
      forEachValue(rawModule.modules, (rawChildModule, key) => {
        this.register(path.concat(key), rawChildModule, runtime)
      })
    }
  }


get (path) {
    return path.reduce((module, key) => {
      return module.getChild(key)
    }, this.root)
  }

再去看看模块对应的getChild和addChild两个函数:

addChild (key, module) {
    this._children[key] = module
  }


getChild (key) {
    return this._children[key]
  }

两个函数都比较简单,重点在于register这个模块。

总体上来看register先通过get这个函数得到模块的父节点,将模块注册到父节点中。再通过深度优先遍历注册所有的模块。

但是怎么说呢,第一次看这个代码的时候我有点像是看语文的阅读理解,所有的字都认识,合起来就不知道什么意思。

通过一个例子来追踪一下register

假设我们有一个模块长这样:

a: {
    modules: {
        b: {
            modules: {
                c: {}, // c是一个模块
                d: {} // d是一个模块
            },
            _children: []
        }
    },
    _children: []
}

1 path的初始值是空。所以很明显,this.root就是a模块。

2 因为a模块的modules值不为空。所以会按循序注册modules里面的每一个模块。当注册b的时候path有[b].

2.1 b注册的时候,parent = this.get([])。也就是得到a模块

2.2 然后a模块添加b为子模块

2.3 这个时候b模块的modules不为空,所以按顺序注册b模块中modules里面的每一个模块。当注册到c的时候,path里面有[b,c]

2.3.1 c注册的时候,parent = this.get([b])。这个时候传入的数组不为空,我们按顺序看看返回的结果是什么。 首先,先明确 reduce函数的回调函数的第一个参数值是上一次的执行结果,第一个当前的数组元素。如果原来的get函数不好理解 的话,可以转换成for循环

var get = function (path) {
    let module = this.root
    for (key in path) {
        if (module.getChild[key])
            module = module.getChild[key]
    }
    return module
}

2.3.2  b模块添加c为子模块

2.3.3    假设c模块的modules为空,那么这个一个分支执行完毕

2.4.1 这时候栈回退到b模块下的d模块,按照上面的流程注册



版权声明:本文为orq18810575870原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。