返回

Vuex 源码:深入 mutation 的更多秘密

前端

Vuex 规定更改 state 的唯一方法是提交 mutation。这是为了能用 devtools 追踪状态变化。那么,提交 mutation 除了最主要的更改 state,它还做了其它一些什么事情呢?让我们来一探究竟。

初步猜测,store 对象的初始化时将 mutation 注册到 store 对象上。让我们来看看源码:

function store (options = {}) {
  const vuex = new Store(options)
  if (plugins !== undefined) {
    each(plugins, plugin => plugin(vuex))
  }
  return vuex
}

很明显,store 函数只是调用了 Store 类的构造函数,将传入的参数作为选项传入,然后返回了 Store 实例。我们还需要继续研究 Store 类,才能找到 mutation 被注册的过程。

class Store {
  constructor (options = {}) {
    // ... 省略部分

    const { mutations } = options
    if (mutations) {
      this._mutations = installModuleMutations(mutations, this, true)
      this._wrappedGetters = installModuleGetters(getters, this)
    }

    // ... 省略部分
  }
}

在 Store 类的构造函数中,如果 options 对象中有 mutations 属性,那么就会调用 installModuleMutations 方法来安装 mutation。

function installModuleMutations (mutations, store, checkVuex) {
  if (__WEEX__) {
    return Vuex.mutations
  } else if (checkVuex) {
    checkVuexMutations(mutations)
  }

  const wrappedMutations = {}
  each(mutations, (mutation, key) => {
    const wrappedMutation = function wrappedMutation (...args) {
      handleMutationCall(this, mutation, args)
    }

    // ... 省略部分
  })

  return wrappedMutations
}

在 installModuleMutations 方法中,会对 mutation 做一些处理,然后将其包装成一个新函数,最后将新函数存储在 wrappedMutations 对象中。

function handleMutationCall (vm, mutation, args) {
  if (vm._committing) {
    return
  }
  vm._committing = true
  const res = mutation.apply(vm, args)
  vm._committing = false
  return res
}

在 handleMutationCall 函数中,会首先检查 vm._committing 属性是否为 true,如果是,则直接返回,不执行 mutation。否则,将 vm._committing 属性设置为 true,执行 mutation,并将执行结果存储在 res 变量中。然后,将 vm._committing 属性设置为 false,并返回 res 变量。

Mutation 是 Vuex 中非常重要的一个概念。它可以帮助我们修改 state,并通过 devtools 来追踪状态变化。通过深入研究 mutation 的源码,我们可以更好地理解 Vuex 的工作原理,并将其应用到我们的项目中。