Vuex
main.js
1 | import Vue from 'vue' |
store/index.js
1 | import Vue from 'vue' |
安装插件
从Vue.use(Vuex)
开始,首先Vuex
是一个对象
与路由插件一样,都会先执行插件的install
方法
1 | function install (_Vue) { |
走进applyMixin
方法
1 | function applyMixin (Vue) { |
versions >= 2
所以调用Vue.mixin({ beforeCreate: vuexInit });
,也就是为所有组件安装beforeCreate
声明周期钩子函数
实例化store
进入new Vuex.Store
1 | ... |
1 | var Store = function Store (options) { |
1)初始化模块:Vuex 允许我们将 store
分割成模块(module)。每个模块拥有自己的 state
、mutation
、action
、getter
store
本身可以理解为一个 root module
,它下面的 modules
就是子模块,看下创建过程
1 | this._modules = new ModuleCollection(options); |
看一下ModuleCollection
构造函数
1 | var ModuleCollection = function ModuleCollection (rawRootModule) { |
这里调用this.register([], rawRootModule, false);
,之后通过new Module(rawModule, runtime)
创建实例
看一下Module
构造函数
1 | var Module = function Module (rawModule, runtime) { |
之后把newModule
赋值给了 this.root
2)安装模块
看下installModule
方法
1 | function installModule (store, rootState, path, module, hot) { |
在这里遍历模块中定义的 mutations
、actions
、getters
分别执行它们的注册工作,实现方式差不多,看一下module.forEachGetter
1 | Module.prototype.forEachGetter = function forEachGetter (fn) { |
进入forEachValue(this._rawModule.getters, fn);
1 | function forEachValue (obj, fn) { |
其实就是获取this._rawModule.getters
的键名数组,遍历它,最后调用registerGetter(store, namespacedType, getter, local);
1 | function registerGetter (store, type, rawGetter, local) { |
最后添加到store._wrappedGetters
上,也就是root store
上
3)初始化 store._vm
看一下resetStoreVM
1 | function resetStoreVM (store, state, hot) { |
在这里遍历store._wrappedGetters
,之后为store.getters
添加属性描述符
也就是访问store.getters
上的属性的时候,其实访问的是store._vm
上的属性
在下面实例化的store._vm
属性
这边调用new Vue
,传入computed
属性,走初始化计算属性watcher
的流程,也传入了data
属性
看一下初始化vm
的时候传入的store
1 | new Vue({ |
上面是初始化的过程,看下$store
是在上面时候挂载到vm
实例上的
之前Vuex
做install
的时候为组件添加的beforeCreate
钩子被调用的时候添加的
1 | function vuexInit () { |
前提是创建vm
实例的时候,参数传入了store
回到上面的例子
执行到render
生成vnode
的时候,会调用计算属性的回调获取count
触发state
的get
又触发count
的get
,拿到count
的值
也就是在这个阶段完成依赖收集
触发点击事件看一下
1 | increment() { |
1)打印this.$store.state.count
,这个没什么好说的
2)第二个获取getters.getCount
,在前面resetStoreVM
的时候,为属性添加的get
描述符被触发
其实就是触发计算属性watcher
的get
方法(这个计算属性watcher
是在上面创建store._vm
实例时候创建的),最后调用到getCount
方法,右边是调用栈
3)this.$store.dispatch('incrementAction');
在这里触发set
之前做过依赖收集,所以这里做派发更新
触发视图更新就是vm._update(vm._render(), hydrating);
小结
也就是在获取state
上的属性的时候会做依赖收集,getter
里的属性在创建store._vm
实例的时候被当做计算属性,会创建计算属性watcher
,在获取的时候会调用回调,dispatch
或者commit
的时候,最后触发视图更新。