在介绍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的值。