指定module_Vuex源码看这个系列就够了:如何理解module与moduleCollection

前言

Vuex源码学习已经连载到了第四篇,前三篇的内容如下:

长篇连载:Vuex源码学习(一)功能梳理

长篇连载:Vuex源码学习(二)脉络梳理

作为一个Web前端,你知道Vuex的install做了什么吗?

正文

整合模块

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

5218ee9c75b6afd0b1ec26b1b935affb.png

在Vuex的constructor中比较靠前的位置有这么两行代码,_modules属性是ModuleCollection的实例对象,之后 _modules属性被频繁使用,这块就是对Vuex的模块进行了一次整合,整合出一个可以被使用的 _modules属性。该怎么整合模块?

先看一下我们我们项目中Store的结构

store/index.js

b4189b9ca7c1d4a5ec48e498c3426ab3.png

moduleList:

8326074f58e050babb984418e2876434.png

moduleSet:

653c9ab1103d98632547f73db67407af.png

结构就是这样的

8ecfb82e469107cbb1ab724d5c35a0d2.png

在以上代码中的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开头的,代表是未经过加工的。

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

在初始化的时候直接开始注册模块,

register这个方法,我们可以看出来,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里 main没有根模块),在每次注册的时候,这个模块有子模块,就把它的path加上(concat)子模块的名字,传入register方法,它的子模块的path就会增加上这个子模块模块的名字,根模块注册的时候path就是[]空数组了。

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

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

总结

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

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值