vuex 源码:初探 vuex 之 install

949 阅读1分钟

前言

vuex 是 vue 的一个插件,需要安装之后,才能在 vue 的基础上使用 vuex。所谓的安装,就是通过全局方法 Vue.use() 使用插件。

先来看看下面一段使用 vuex 的代码:

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 对象,将其挂载在 vue 实例上,然后就可以在各组件里使用 this.$store 来管理状态。接下来,我们就从 vuex 的源码入手,来探索 vuex 是如何被安装的。

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

解读

下载并打开项目,不知从何下手。那就先打开 package.json 吧,看到 script 的 build 命令里,都是去找 bulid 这个目录下的文件,还有不知道的 rollup 命令字样。于是打开 build 目录,看到了 rollup.config.js 并打开它。很幸运,找到了 entry 是 src/index.js。大胆猜测,rollup 是一个打包工具,入口文件是 entry,所以源码应该是在 src 目录下。

前面都只是热身动作,找到了源码,接下来就是真正地阅读源码了。

index.js

进入 src 目录,打开 index.js,发现有 300 多行代码,是准备开始逐行啃下来?别傻了,把所有的 function 先折叠起来,然后看到最下面的代码:

export default {
  Store,
  install,
  mapState,
  mapMutations,
  mapGetters,
  mapActions
}

当当当当,这里就是 vuex 暴露出来的 API,一点也不多是吧。我们只需先关注 install 这个 API。Vue.js 的插件应当有一个公开方法 install。对,就是 343 行的这个 install 方法:

function install (_Vue) {
  if (Vue) {
    console.error(
      '[vuex] already installed. Vue.use(Vuex) should be called only once.'
    )
    return
  }
  Vue = _Vue
  applyMixin(Vue)
}

install

这个 install 好像没做什么事情,最主要就是调用了 applyMixin 方法。于是找到了 mixin.js 文件,里面便是这个方法的实现。

我们需要关注的是 vue 2.0 版本的代码,所以直接忽视 1.0 的版本,然后生命周期则是使用 beforeCreate。经过一系列的判断,最后可以把代码简化成这样:

export default function(vue) {
  Vue.mixin({ beforeCreate: vuexInit })
  
  /**
   * Vuex init hook, injected into each instances init hooks list.
   */

  function vuexInit () {
    const options = this.$options
    // store injection
    if (options.store) {
      this.$store = options.store
    } else if (options.parent && options.parent.$store) {
      this.$store = options.parent.$store
    }
  }
}

代码实现了全局注册混合对象。从 vuexInit 这个方法得知,实际做的事情就是组件取得 vue 对象的 options,把options 里的 store 赋值给 store。当然如果options 没有 store,则向其 parent 向上查找并赋值。

因此,我们可以在各个组件里使用到 this.$store 来进行状态的管理,实际上就是我们初始化的 store 对象。

总结

本篇从 vuex 的安装代码 Vue.use(Vuex) 出发,然后找到 vuex 实现的 install 方法,到最后得知 vuex 实现了全局注册混合对象 applyMixin,即给每个 vue 组件都添加了 $store 属性。而 store 则是从实例化 vue 根对象时传进去,所以接下来,我们要研究的就是这个 store 对象。