• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Vuex源码学习四module和moduleCollection

武飞扬头像
酸楚与甘甜
帮助3

如果你还不知道Vuex是怎么安装的,请移步Vuex源码学习(三)install都做了哪些事情

整合模块

这一节该分析模块的是怎么被整合的,以及要整合成什么样子。

学新通

在Vuex的constructor中比较靠前的位置有这么两行代码,_modules属性是ModuleCollection的实例对象,之后 _modules属性被频繁使用,

这块就是对Vuex的模块进行了一次整合,整合出一个可以被使用的 _modules,而_moduleNamespaceMap是一个空对象

该怎么整合模块?

先看一下我们我们项目中Store的结构 store/index.js

学新通

moduleList:

学新通

moduleSet:

学新通

结构就是这样的

学新通

在以上代码中的modules下的数据,我都称它是伪(未加工)模块,因为它还不具有模块的功能。 当我们实例化Vuex.Store这个类的时候接收的参数options就会直接交给moduleCollection来处理。参数options是什么呢?就是上面图中这样结构的数据, 想要处理成什么样子? 下面看一下ModuleCollection是怎么处理的

export default class ModuleCollection {
  constructor (rawRootModule) {
    // register root module (Vuex.Store options)
    // 注册模块并链接
    this.register([], rawRootModule, false)
  }
  ...
  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 {
      // path.slice(0,-1)就可以拿到父模块的path。
      // get方法可以根据path来找到对应的模块。
      const parent = this.get(path.slice(0, -1))
      // 将子模块挂载到父模块上
      parent.addChild(path[path.length - 1], newModule)
    }
    // register nested modules
    if (rawModule.modules) {
      // 遍历每个模块的modules(目的是获取所有子模块)
      forEachValue(rawModule.modules, (rawChildModule, key) => {
      // 为什么要path.concat(key)?
        // 依次注册子模块。
        this.register(path.concat(key), rawChildModule, runtime)
      })
    }
  }
}

在Vuex与vue-router的源码中,命名变量是很有规律的, 在开发人员使用这两个框架的时候,传递进去的参数,在使用时命名的变量名都是raw开头的,代表是未经过加工的。

学新通

将未经过加工的伪模块处理成真正可以使用的模块。

在初始化的时候直接开始注册模块, moduleCollection的这个类的任务是把生成的模块合理的链接起来,而模块的生成交给了Module这个类。

所以register方法就是把根模块以及所有的子模块从一个伪(未加工)模块变成一个真正的模块并且链接起来。 遍历树形结构用什么方法? 递归!

register都做了什么?

  1. 筛选出不符合规则的模块,报错提示。
  2. 将伪(未加工)模块加工成一个真正的模块。
  3. 将加工好的模块挂载在它的父模块上。
  4. 如果这个模块有modules属性(模块有自己的子模块)让每个子模块重复以上操作

递归的出口:rawModule.modules为false(模块没有子模块) ,也就是每个模块都没有子模块需要注册了,那就代表全部加工与链接完毕。

分析register的三个参数

register接收三个参数,path、rawModule、hot。

hot这个参数目前看来不关键。

rawModule是伪(未加工)模块

那path的作用是什么呢?

path的作用很大,大家类比下前端页面的dom树的Xpath,如果我想知道这个节点的位置,需要知道这个父节点的位置,然后一层一层的向上知道根结点,有了Xpath就可以直接找到这个节点,

Vuex也是一样的想知道某个模块的位置,只需要提供根结点到他的一个path,path按顺序存储着根模块到它本身的所有祖先模块(根模块没有名字,又不能把第一个放一个空,所以path里 面没有根模块),在每次注册的时候,这个模块有子模块,就把它的path加上(concat)子模块的名字,在子模块执行register方法时,path就比它的父模块多一个父模块的名字,所以根模块注册的时候传入path就是[](空数组)了。

ModuleCollection的get方法可以根据path来获取指定的模块,在挂载的时候十分有用,

学新通

,使用reduce的方法,按照数组的顺序,一层一层的找目标模块。

path对以后要讲的设置命名空间也很有帮助。

总结

  1. ModuleCollection这个类,主要完成了模块的链接与整合,生成模块的任务交给了Module这个类。
  2. 模块的链接与整合通过递归完成。
  3. path可以让moduleCollection快速找到对应模块。

下一章讲述生成的module具体可以做什么

我是一个应届生,最近和朋友们维护了一个公众号,内容是我们在从应届生过渡到开发这一路所踩过的坑,已经我们一步步学习的记录,如果感兴趣的朋友可以关注一下,一同加油~

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhffffkb
系列文章
更多 icon
同类精品
更多 icon
继续加载