vuex 中的commit源码解读

在介绍commit之前,先介绍一下subscribe。

这个API的官方文档在这里https://vuex.vuejs.org/zh/api/#watch

订阅 store 的 mutation。handler 会在每个 mutation 完成后调用,接收 mutation 和经过 mutation 后的状态作为参数:

store.subscribe((mutation, state) => {
  console.log(mutation.type)
  console.log(mutation.payload)
})

 先来看看这个API的源码:

subscribe (fn) {
    return genericSubscribe(fn, this._subscribers)
  }

function genericSubscribe (fn, subs) {
  if (subs.indexOf(fn) < 0) {
    subs.push(fn)
  }
  return () => {
    const i = subs.indexOf(fn)
    if (i > -1) {
      subs.splice(i, 1)
    }
  }
}

源码很简单,就是往_subscribers数组中放我们配置的函数。

再来看看commit的源码。

commit (_type, _payload, _options) {
    // check object-style commit
    const {
      type,
      payload,
      options
    } = unifyObjectStyle(_type, _payload, _options)

    const mutation = { type, payload }
    const entry = this._mutations[type]
    if (!entry) {
      if (process.env.NODE_ENV !== 'production') {
        console.error(`[vuex] unknown mutation type: ${type}`)
      }
      return
    }
    this._withCommit(() => {
      entry.forEach(function commitIterator (handler) {
        handler(payload)
      })
    })
    this._subscribers.forEach(sub => sub(mutation, this.state))

    if (
      process.env.NODE_ENV !== 'production' &&
      options && options.silent
    ) {
      console.warn(
        `[vuex] mutation type: ${type}. Silent option has been removed. ` +
        'Use the filter functionality in the vue-devtools'
      )
    }
  }

这个代码总体也很好理解,就是先讲我们提交commit对应的_mutations传到_withCommit这个内置函数中。我们再来看看这个内置函数的是干什么的:

_withCommit (fn) {
    const committing = this._committing
    this._committing = true
    fn()
    this._committing = committing
  }

代码也很见到,就是在对应的_mutations函数执行之前将_committing这个变量赋值为true,执行完毕后将它还原。那么这个变量究竟是干什么用的呢,接着看。

在vuex构造函数中调用了resetStoreVM这个函数。这个函数的最后有这样的一句话:

if (store.strict) {
    enableStrictMode(store)
  }

借着看看这个函数

function enableStrictMode (store) {
  store._vm.$watch(function () { return this._data.$$state }, () => {
    if (process.env.NODE_ENV !== 'production') {
      assert(store._committing, `do not mutate vuex store state outside mutation handlers.`)
    }
  }, { deep: true, sync: true })
}


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

看到这里就明了了,如果strict这个参数是true的话,就会对store的state进行监听,当state发生变化的时候,查看_committing这个值是否是true,如果不是的话,就抛出一个错。所以_withCommit这个内置函数会在_mutations对应的函数执行之前将它赋值为true,确保在_mutations可以改变state。执行完毕之后还原,确保其他途径是不可以改变state的值。

 

你可能感兴趣的:(vue)