Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
一个库、框架的出现肯定是为了解决某一种问题,Vuex 也不例外,它主要解决了以下两种:
它是把组件的共享状态抽取出来,以一个全局单例模式来管理。原理图如下:
当然 Vuex 肯定也不是适用于所有的场景,因为它带来了一些它自己的概念:State、Getters、Mutations、Actions、Modules 。若你的项目够简单,建议还是不要用 Vuex。
源码分析
我们从 Vuex 的使用方法开始入手:
初始化:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
从根组件注入 store:
new Vue({
el: '#app',
store: store,
})
从上面可以看出是通过 Vue.use 来使用 Vuex 的那 Vue.use 是什么呢?作用主要是来使用 Vue 的插件的。源码如下:
export function initUse (Vue: GlobalAPI) {
Vue.use = function (plugin: Function | Object) {
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
// 防止多次 use
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// additional parameters
const args = toArray(arguments, 1)
args.unshift(this)
// 根据 plugin 类型的不同执行不同逻辑。1.对象的时候,则执行它身上的intall 方法,2. plugin 函数时则直接执行
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}
installedPlugins.push(plugin)
return this
}
}
那 Vuex 既然是通过 Vue.use 调用的,那 Vuex 是要满足调用条件的,看下源码( 2.4.0 版本):
let Vue;
class Store{
...
}
function install(_Vue){
// 这里也是防止多次调用 Vue.use
if (Vue) {
console.error(
'[vuex] already installed. Vue.use(Vuex) should be called only once.'
)
return
}
Vue = _Vue
applyMixin(Vue)
}
export default {
Store,
install,
version: '__VERSION__',
mapState,
mapMutations,
mapGetters,
mapActions
}
源码中看出确实包括 install 方法,它里面很简单只是调用了 applyMixin 方法:
export default function (Vue) {
const version = Number(Vue.version.split('.')[0])
if (version >= 2) {
// Vue 2.x 使用 mixin 方法 把 vuexInit 混入到 beforeCreate 钩子中
Vue.mixin({ beforeCreate: vuexInit })
} else {
...
}
function vuexInit () {
...
}
}
从上看出 install 方法根据 Vue 版本不同,使用不同的方法把 vuexInit 混入到组件中,Vuex 的使用是把实例化的 store 以选项的形式放到 Vue 根组件中,那子组件是如何获得 store 的呢?那就要依靠 vuexInit 了:
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) {
// 子组件 $store 引用父组件的 $store 形成一条链,保证全部使用的是同一个 store 对象。
this.$store = options.parent.$store
}
}
以上代码主要区分了根组件和子组件是如何获取 store 对象的。至此 Vuex 是如何注入到所有组件的就讲完了。
欢迎访问我的作品?