Vuex 源码深度解析
Vuex 思想
在解读源码之前,先来简单了解下 Vuex 的思想。
Vuex 全局维护着一个对象,使用到了单例设计模式。在这个全局对象中,所有属性都是响应式的,任意属性进行了改变,都会造成使用到该属性的组件进行更新。并且只能通过 commit 的方式改变状态,实现了单向数据流模式。
Vuex 解析
Vuex 安装
在看接下来的内容前,推荐本地 clone 一份 Vuex 源码对照着看,便于理解。
在使用 Vuex 之前,我们都需要调用 Vue.use(Vuex) 。在调用 use 的过程中,Vue 会调用到 Vuex 的 install 函数
install 函数作用很简单
确保 Vuex 只安装一次
混入
beforeCreate钩子函数,可以在组件中使用this.$store
export function install(_Vue) {
// 确保 Vuex 只安装一次
if (Vue && _Vue === Vue) {
if (process.env.NODE_ENV !== 'production') {
console.error(
'[vuex] already installed. Vue.use(Vuex) should be called only once.'
)
}
return
}
Vue = _Vue
applyMixin(Vue)
}
// applyMixin
export default function(Vue) {
// 获得 Vue 版本号
const version = Number(Vue.version.split('.')[0])
// Vue 2.0 以上会混入 beforeCreate 函数
if (version >= 2) {
Vue.mixin({ beforeCreate: vuexInit })
} else {
// ...
}
// 作用很简单,就是能让我们在组件中
// 使用到 this.$store
function vuexInit() {
const options = this.$options
if (options.store) {
this.$store =
typeof options.store === 'function' ? options.store() : options.store
} else if (options.parent && options.parent.$store) {
this.$store = options.parent.$store
}
}
}Vuex 初始化
this._modules
本小节内容主要解析如何初始化 this._modules
接下来看 this._modules 的过程,以 以下代码为例
对于以上代码,store 可以看成 root 。在第一次执行时,会初始化一个 rootModule,然后判断 root 中是否存在 modules 属性,然后递归注册 module 。对于 child 来说,会获取到他所属的 parent, 然后在 parent 中添加 module 。
installModule
接下来看 installModule 的实现
resetStoreVM
接下来看 resetStoreVM 的实现,该属性实现了状态的响应式,并且将 _wrappedGetters 作为 computed 属性。
常用 API
commit 解析
如果需要改变状态的话,一般都会使用 commit 去操作,接下来让我们来看看 commit 是如何实现状态的改变的
dispatch 解析
如果需要异步改变状态,就需要通过 dispatch 的方式去实现。在 dispatch 调用的 commit 函数都是重写过的,会找到模块内的 mutation 函数。
各种语法糖
在组件中,如果想正常使用 Vuex 的功能,经常需要这样调用 this.$store.state.xxx 的方式,引来了很多的不便。为此,Vuex 引入了语法糖的功能,让我们可以通过简单的方式来实现上述的功能。以下以 mapState 为例,其他的几个 map 都是差不多的原理,就不一一解析了。