接下来咱们则开始要研究的是 vuex 的 store 对象。html
store 对象中有一个属性叫 state。state 包含了所有的应用层级状态。应用中的各个组件若使用了 state,则会保持与同步最新的状态。state 就比如是 vue 中的 data,但它是整个应用的 data。vue
举个简单的例子:应用中的子组件 a 和子组件 b 用到了 state.count,两个组件是非父子关系。这时,子组件 a 修改了 state.count,子组件 b 中的 state.count 也会相应修改。react
那咱们就来看看,vuex 是如何在各个组件中作到监听 state 的属性的。git
注:本次阅读的是 vuex 的 2.0.0 版本,源码请戳 这里。github
在开始阅读源码以前,我一直有一个疑惑。我在组件 a 修改了 state.count,组件 b 是怎么监听到 state.count 的改变的?难道是 store 里对 state 作了相似 object.defineproperty() 的处理。vuex
带着疑惑,开始啦.....app
从哪开始切入呢?就从 store 对象被实例化的代码中开始吧。ide
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 0
}
});
new Vue({
el: '#app',
store,
// ...
});
复制代码
store 对象是经过 new Vuex.Store 被实例化出来的,打开 src/index.js
文件,最下面的代码中能够看到 vuex 暴露出的 Store 这个 API:函数
export default {
Store,
install,
mapState,
mapMutations,
mapGetters,
mapActions
}
复制代码
找到 Store 这一个类,挺长的一大段代码。老办法,所有方法折叠不看,只看构造函数 constructor。开启过滤之眼,过滤掉与 state 无关的代码,最后能够把代码简化成这样:学习
constructor (options = {}) {
const {
state = {}
} = options
// init root module.
// this also recursively registers all sub-modules
// and collects all module getters inside this._wrappedGetters
installModule(this, state, [], options)
// initialize the store vm, which is responsible for the reactivity
// (also registers _wrappedGetters as computed properties)
resetStoreVM(this, state)
}
复制代码
瞬间代码少了好多,接下来只须要关注 installModule
与 resetStoreVM
两个方法的实现便可。紧接着,再透露一个好消息,installModule
看了一眼,是关于 module 的初始化,等之后研究 module
再看也不迟,因此只须要研究 resetStoreVM
便可。
定位到 resetStoreVM
方法,再次过滤,其中 Vue.config.silent 去 vue 的官网上搜了一下,是取消 vue 全部的日志与警告的功能,因此也过滤掉,剩下代码以下:
function resetStoreVM (store, state) {
// use a Vue instance to store the state tree
store._vm = new Vue({
data: { state }
})
}
复制代码
resetStoreVM
函数作的事情就是给 store 添加一个 _vm
属性,并将 state 做为一个 vue 对象的 data,最后将这个 vue 对象赋值给 _vm。因此到这里咱们知道了 store 类的构造函数为其添加了一个 _vm 属性。
构造函数解析完毕,接下来得继续找跟 state 相关的方法,因而找到了 set
和 get
方法:
get state () {
return this._vm.state
}
set state (v) {
assert(false, `Use store.replaceState() to explicit replace store state.`)
}
复制代码
set
方法没什么好说的,意思就是 store 不给你直接修改 state(但实际上是能够修改 state 对象的属性,先无论那么多了)。
get
方法返回了刚刚构造函数添加的 _vm 属性的一个 data(state)。阅读到这里,这下咱们应该知道为何组件 a 修改了 state.count,组件 b 也会跟着变了吧。由于 state 就是一个新的 vue 对象里 data 的一个属性啊。到这里若是还不明白,是否是要回去 vue 官网从新学习 data 啦。
这样总算是解决了我刚开始阅读时的疑惑了。仔细思考一下,这不就是 vue 官网非父子组件的通讯中的 bus 注入到整个应用的 vue 对象中吗?!
本篇咱们了解了 store 的 state,知道它是经过 new 一个新的 vue 对象 _vm 来监听的,而这个 _vm 又是绑在 store 上的。因此经过这一系列的关系,最后咱们能在各个组件中使用到被监听的 this.$store.state。