Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vuex源码分析二(了解Store构造函数) #11

Open
Abiel1024 opened this issue May 18, 2018 · 0 comments
Open

vuex源码分析二(了解Store构造函数) #11

Abiel1024 opened this issue May 18, 2018 · 0 comments

Comments

@Abiel1024
Copy link
Owner

Abiel1024 commented May 18, 2018

构造函数Store

在我们使用vuex时,通常是这样:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

实例化一个Store类,传入的也就是我们定义好的 actions、getters、mutations、state等,甚至当我们有多个子模块的时候,我们可以添加一个 modules 对象。所以最核心的部分就是Store类了。
因为内容比较多,所以一定要分开一部分一部分看。

先总的看store.js中定义的store类
image

虽然代码有很多,但是并不是一下子就用到,在我们new一个store实例的时候,传入一个对象,会先调用constructor方法。

constructor

通过代码分析:
第一部分

  if (!Vue && typeof window !== 'undefined' && window.Vue) {
    install(window.Vue)
  }

  if (process.env.NODE_ENV !== 'production') {
    assert(Vue, `must call Vue.use(Vuex) before creating a store instance.`)
    assert(typeof Promise !== 'undefined', `vuex requires a Promise polyfill in this browser.`)
    assert(this instanceof Store, `store must be called with the new operator.`)
  }

  const {
    plugins = [],
    strict = false
  } = options

这一部分显示判断了是否已经执行了install方法,如果没有就重新install。
接下来是在非正式环境利用assert‘断言函数’,判断了Vue、Promise、至于第三个还不是特别明白,等以后明白了在补充吧。
assert‘断言函数’,在util.js中。对条件进行判断,判断为失败,则报错。

export function assert (condition, msg) {
  if (!condition) throw new Error(`[vuex] ${msg}`)
}

非常的简单,但是这种编程方式很优雅。

接下来利用es6 的结构赋值拿到 options 里的plugins 和 strict。plugins 表示应用的插件、strict 表示是否开启严格模式。结合下面的两行代码,分别把模式赋值到本身对象中,以及注入插件。

  // strict mode
  this.strict = strict

  // apply plugins
  plugins.forEach(plugin => plugin(this))

插件的功能的话就不多说了。严格模式下会观测所有的 state 的变化,建议在开发环境时开启严格模式,线上环境要关闭严格模式,否则会有一定的性能开销。

第二部分

  // store internal state
  this._committing = false
  this._actions = Object.create(null)
  this._actionSubscribers = []
  this._mutations = Object.create(null)
  this._wrappedGetters = Object.create(null)
  this._modules = new ModuleCollection(options)
  this._modulesNamespaceMap = Object.create(null)
  this._subscribers = []
  this._watcherVM = new Vue()

  // bind commit and dispatch to self
  const store = this
  const { dispatch, commit } = this
  this.dispatch = function boundDispatch (type, payload) {
    return dispatch.call(store, type, payload)
  }
  this.commit = function boundCommit (type, payload, options) {
    return commit.call(store, type, payload, options)
  }

这一部分主要是声明了store内部的一些属性,以及改变dispatch和commit的this指向。

  • ._committing 标志一个提交状态,作用是保证对 Vuex 中 state 的修改只能在 mutation 的回调函数中,而不能在外部随意修改 state。
  • this._actions 用来存储用户定义的所有的 actions。
  • this._actionSubscribers 用来存储所有派发 action 的订阅者,主要是提供给插件辅助开发。
  • this._mutations 用来存储用户定义所有的 mutatins。
  • this._wrappedGetters 用来存储用户定义的所有 getters 。
  • this._modules = new ModuleCollection(options) 将配置转成Module实例。下面在具体分析。
  • this._modulesNamespaceMap = Object.create(null) 用来存储用户开启namespaced的module,主要在map方法中用到。
  • this._subscribers = [] 用来存储所有对 mutation 变化的订阅者。主要是提供给插件辅助开发。
  • this._watcherVM = new Vue()是一个 Vue 对象的实例,主要是利用 Vue 实例方法 $watch 来观测变化的。

下面这段则是利用call将dispatch和commit方法的this指向知道当前store

  this.dispatch = function boundDispatch (type, payload) {
    return dispatch.call(store, type, payload)
  }
  this.commit = function boundCommit (type, payload, options) {
    return commit.call(store, type, payload, options)
  }

第三部分

  // strict mode
  this.strict = strict

  const state = this._modules.root.state

  // init root module.
  // this also recursively registers all sub-modules
  // and collects all module getters inside this._wrappedGetters
  installModule(this, state, [], this._modules.root)

  // initialize the store vm, which is responsible for the reactivity
  // (also registers _wrappedGetters as computed properties)
  resetStoreVM(this, state)

  // apply plugins
  plugins.forEach(plugin => plugin(this))

  if (Vue.config.devtools) {
    devtoolPlugin(this)
  }

关于严格模式和插件就不多说了,这里只是多了一个如果检测到devtools就自动注入devtooPlugin。
剩下的也是最重要的就是installModuleresetStoreVM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant