前言
?对于Vuex相信大家是常用,那么Vuex作为Vue生态中最重要的一部分,专为Vue.js应用的状态管理模式,每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state ),并且Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样可以方便地跟踪每一个状态的变化。
原理分析
Vuex装载分析
?这个问题实际就是问到Vuex的store是如何装载到组件中的,首先利用了Vue的插件机制使用Vue.use(Vuex) 来去安装Vuex插件,那么此时会调用vuex的install方法,当调用install时此时会利用mixin机制在beforeCreate阶段去执行vuexInit。核心源码如下:
Vue.mixin({ beforeCreate: vuexInit });
?我们可以发现在beforeCreate阶段调用了vuexInit方法,我们分析一下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) {
this.$store = options.parent.$store
}
}
?分析如上代码:将初始化Vue根组件时传入的store设置到this对象的$store属性上,子组件从其父组件引用$store属性,层层嵌套进行设置。在任意组件中执行 this.$store 都能找到装载的那个store对象。
Vuex中的state与getter
?vuex的Store 会划分出 state 和 getters 两个数据区。getter是从store的state中派生出的状态。那么首先我们先看我们是如何访问state的?
get state () {
return this._vm._data.$$state
}
?当我们使用this.$store.state.xxx 去获取xxx属性时,实际获取的是store挂载到_vm中store._vm.data.$$state 中的数据。 ?state是如何挂载上去的?我们在Store constructor找到了核心函数resetStoreVM,观察resetStoreVM的核心代码,其主要做的事情是初始化了一个vue实例_vm,由于vue的data是响应式的,所以,$$state也是响应式的,那么当我们 在一个组件实例中 对state.xxx进行 更新时,基于vue的data的响应式机制,所有相关组件的state.xxx的值都会自动更新,视图自然也会自动更新,核心代码如下:
store._vm = new Vue({
data: {
$$state: state
},
computed
})
?上面所介绍的是state,那么接下来我们介绍一下getter,其核心源码也是在 resetStoreVM中,核心源码如下:
forEachValue(wrappedGetters, (fn, key) => {
computed[key] = partial(fn, store)
Object.defineProperty(store.getters, key, {
get: () => store._vm[key],
enumerable: true
})
})
?until.js的部分源码如下:
export function forEachValue (obj, fn) {
Object.keys(obj).forEach(key => fn(obj[key], key))
}
export function partial (fn, arg) {
return function () {
return fn(arg)
}
}
?对wrappedGetters 进行处理,让getter 存储至computed对象上,对getter对象的属性进行数据劫持,当触发get时,返回store._vm[key] ,最后将computed挂载到vue实例上,当做计算属性。
store._vm = new Vue({
data: {
$$state: state
},
computed
})
总结
- vuex利用了vue的mixin机制,混合 beforeCreate 钩子 将store注入至vue组件实例上,并注册了 vuex store的引用属性 $store。
- vuex的state是借助vue的响应式data实现的。getter是借助vue的计算属性computed特性实现的。
Vue源码系列文章:
|