Vuex源码解析(一):Module初始化

时间:2020-9-9 作者:admin

注册

install -> applyMixin->vuexInit

这里只分析Vue2的注册,因为Vue1我也没用过。

其实就是调用了Vue的静态方法mixin。静态方法mixin是全局混入,会在每一个实例的options内添加beforeCreate回调函数。

Vuex源码解析(一):Module初始化

vuexInit内的options指的是每一个vue实例的options。

在最外面的App根组件上引入了store属性,因此app组件上就有了$store属性,

随后以this.store=options.parent.store = options.parent.store=options.parent.store的方式将所有vm实例的$store在组件初始化时全部指向了app根组件的store值。

即,this.$store 其实是 Store的实例。Vuex可以创建多个Store实例,但是一般而言一个Store已经够用了。

Vuex其实是一种状态管理方式,脱离了Vue也可以使用。

Vuex源码解析(一):Module初始化

初始化模块(一):new Module与建立Module的父子关系

Vuex源码解析(一):Module初始化

ModuleCollection构造函数:register

构造函数调用了register方法

Vuex源码解析(一):Module初始化

这里根本上是根据options来创建module并且建立父子关系。具体阐述如下注释:

Vuex源码解析(一):Module初始化

Module类其实内部保存的数据不多,只是一个rowModule与state而已。

Vuex源码解析(一):Module初始化

初始化模块(二):installModule

Vuex源码解析(一):Module初始化

installModule

获取模块的命名空间,然后递归安装所有的模块,其中有几个重要的方法要分析一下。

Vuex源码解析(一):Module初始化

makeLocalContext:创建模块的本地执行上下文环境

这里传入的store为当前的store实例,命名空间为当前安装模块的命名空间,path为路径数组,root Module为[]

Vuex源码解析(一):Module初始化

makeLocalContext

Vuex源码解析(一):Module初始化

makeLocalGetters

使用gettersProxy代理对象,当获取模块内部的getters时,其实访问的是gettersProxy对象,gettersProxy对象做的事情就是方便在模块内部访问某一个getter时,可以不添加命名空间就可以取值。

Vuex源码解析(一):Module初始化

至此,const local = (module.context = makeLocalContext(store, namespace, path))的过程已经全部清楚了

registerMutation

Vuex源码解析(一):Module初始化

registerAction

Vuex源码解析(一):Module初始化

registerGetters

Vuex源码解析(一):Module初始化

初始化模块(三):resetStoreVM(this, state)

将getters,state加入响应式系统,只有这两个属性是因为vuex中只有这两个属性有关,action与dispatch都是改变数据的动作。

Vuex源码解析(一):Module初始化

resetStoreVM,其实就做了两件事:

1. 给store添加getters属性,将所有的getter都添加到该属性内;

2. new Vue,构造函数内传入computed与data,computed值为包裹后的getters,data为state。这样getters与state的数据就加入了响应式系统。

Vuex源码解析(一):Module初始化

小结

在Vuex中,数据是存储在module内部的state对象与getters对象之中。

简单来讲,可以看到store上定义了很多的内部属性,最难的部分其实是getters,因为很绕。

但是从数据获取途径的角度来看就会迎刃而解。

数据从store实例获取

初始化Vuex执行installModule的时候,registerGetter函数将原始的getter函数座一层包裹(warappedGetter),存储在store._wrappedGetters中。

执行resetStoreVM的时候,store.getters添加了store._wrappedGetters中所有的getters。

store._wrappedGetters是个中转站,工具人

通过store.getters[key]直接获取getter,值为wrappedGetter,传入了local.getters,local.state,store.getters,store.state。

所以rawGetter可以获取到上述参数。

数据从内部获取的角度

module内部的mutations对象与actions对象内的方法可以获当前module的getters/state与全局的state。

当在以module内部的视角看数据的时候,是不会在意namespace这个值的,因为在module内部就只有一个namespace。因此使用了gettersProxy对象来将当前module的getter与store实例上的getters联系起来,即gettersProxy的key不带命名空间,值为store.getters内带有命名空间的getter函数(wrappedGetter)。

local对象

local对象内有getters,为了提升性能,做了一层Cache,将getters保存到_makeLocalGettersCache对象,key为命名空间,value为gettersProxy。

local.getters

local.getters拿到了gettersProxy的值。那么将local传入wrapperedGetter函数就可以获取local的值了,同样地,传入store就可以拿到全局的值。传入其他处理后的action,dispatch就可以拿到特定的local和全局的getters/state。

所以,看起来是在内部访问的数据,其实最终还是访问了store.getters。而使用gettersProxy对象也是为了做一层缓存,并且可以在module内部取getter值的时候可以不写命名空间。

其他

在commit与dispatch的方法中含有type参数,在module内部书写type的时候,makelocalContext函数已经为type添加了namespace,因此可以直接写不带namespace的type参数。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。