vuex 源码:深入 vuex 之 state

前言

接下来我们则开始要研究的是 vuex 的 store 对象。

store 对象中有一个属性叫 state。state 包含了全部的应用层级状态。应用中的各个组件若使用了 state,则会保持与同步最新的状态。state 就好比是 vue 中的 data,但它是整个应用的 data。

举个简单的例子:应用中的子组件 a 和子组件 b 用到了 state.count,两个组件是非父子关系。这时,子组件 a 修改了 state.count,子组件 b 中的 state.count 也会相应修改。

那我们就来看看,vuex 是如何在各个组件中做到监听 state 的属性的

注:本次阅读的是 vuex 的 2.0.0 版本,源码请戳 这里

解读

在开始阅读源码之前,我一直有一个疑惑。我在组件 a 修改了 state.count,组件 b 是怎么监听到 state.count 的改变的?难道是 store 里对 state 做了类似 object.defineproperty() 的处理。

带着疑惑,开始啦.....

从哪开始切入呢?就从 store 对象被实例化的代码中开始吧。

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

找到 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)
}
复制代码

瞬间代码少了好多,接下来只需要关注 installModuleresetStoreVM 两个方法的实现即可。紧接着,再透露一个好消息,installModule 看了一眼,是关于 module 的初始化,等以后研究 module 再看也不迟,所以只需要研究 resetStoreVM 即可。

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 属性。

set 与 get

构造函数解析完毕,接下来得继续找跟 state 相关的方法,于是找到了 setget 方法:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值