前端日报--学习vuex(一)

在vue烂在满大街的情况下,面试中问到vue核心插件实现原理是很平常的事情。
抱着学习的态度,我们来学习下vuex的源码。

在学习之前,我们希望得到什么答案呢?

在很长的时间,我们都在讨论vuex的关键的几个可以被用于单向流动的固定节点:dispatch->acition(commit)->mutation->state。所以本坑希望我们读完源码后,我们知道为什么vuex一定要遵循这几个节点单向的流动,状态是怎么衔接过去的?
第二个问题就是,vuex它如何实现响应式的状态变化?
第三个问题就是,我们是否能够准确口述vuex大致实现和管理策略呢?

从头开始

vue的入口文件是src\index.js,打开看看:
和其他插件一样,在项目通过use(vuex)来调用install方法来安装vuex的,除此之外还提供其他方法,比如常常在各个模块使用的map类函数。

import { Store, install } from './store'
import { mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers } from './helpers'

export default {
  Store,
  install,
  version: '__VERSION__',
  mapState,
  mapMutations,
  mapGetters,
  mapActions,
  createNamespacedHelpers
}

我们先看看install方法,当运行Vue.use(vuex)便开始启动install。为了防止多次调用install方法引发的多次安装,代码中通过赋值比较的方式来实现。看似简单却解决了这个问题。这里有个小点:如果多次Vue.use(vuex),封装的use代码里会先检查Vue_installedPlugins数组是否有该插件,如果有则直接返回,并不会进入插件install里。

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

可以看到代码根据版本来使用不同的方式来applyMixin,如果是2.0版本则把vuexInit初始化的方法混入beforeCreate钩子里,如果不是,则合并到_init原型方法里头。vuexInit方法能够让实例中各个层级能够访问到和根节点一样的store.自此install过程就完成了。

export default function (Vue) {
  const version = Number(Vue.version.split('.')[0])

  if (version >= 2) {
    Vue.mixin({ beforeCreate: vuexInit })
  } else {
    // override init and inject vuex init procedure
    // for 1.x backwards compatibility.
    const _init = Vue.prototype._init
    Vue.prototype._init = function (options = {}) {
      options.init = options.init
        ? [vuexInit].concat(options.init)
        : vuexInit
      _init.call(this, options)
    }
  }

  /**
   * Vuex init hook, injected into each instances init hooks list.
   */

  function vuexInit () {
    const options = this.$options
    // store injection
    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
    }
  }
}

下一节,store的构造函数说起。

你可能感兴趣的:(前端日报--学习vuex(一))