当我们创建一个vuex
时候,也就是创建一个store
实例。我们使用vuex
其实也就是对store
实例的使用
import Vuex from 'vuex'
const store = new Vuex.Store({ ...options })
关于mutations
当我们使用mutations
时,其实也就是在store
实例上注册一个mutation
。因为mutation
处理函数总是接受 state
作为第一个参数(如果定义在模块中,则为模块的局部状态),第二个参数可选。这也就是为什么我们可以store.commit('func')
来调用相对应的mutation
。
//vuex/src\store.js vuex源码
this.commit = function boundCommit (type, payload, options) {
return commit.call(store, type, payload, options)
}
关于actions
当我们使用actions
时,其实也是在store
上注册 action
。处理函数总是接受 context
作为第一个参数。关于context
其实是个对象,包含以下属性:
{
state, // 等同于 `store.state`,若在模块中则为局部状态
rootState, // 等同于 `store.state`,只存在于模块中
commit, // 等同于 `store.commit`
dispatch, // 等同于 `store.dispatch`
getters, // 等同于 `store.getters`
rootGetters // 等同于 `store.getters`,只存在于模块中
}
这也是为什么我们可以使用store.dispatch('increment')
来分发action。
当我们使用store.dispatch('increment')
时,会在当前store实例上的_actionSubscribers
数组中根据传入的type
来遍历查找相对应的action来触发相对应的mutation
。
dispatch (_type, _payload) {
const action = { type, payload }
const entry = this._actions[type]
const result = entry.length > 1
? Promise.all(entry.map(handler => handler(payload)))
: entry[0](payload)
return new Promise((resolve, reject) => {
result.then(res => {
try {
this._actionSubscribers
.filter(sub => sub.after)
.forEach(sub => sub.after(action, this.state))
} catch (e) {
if (__DEV__) {
console.warn(`[vuex] error in after action subscribers: `)
console.error(e)
}
}
resolve(res)
}
}
而我们通过commit
来遍历_mutations
处理相对应的mutation handler
。
commit (_type, _payload, _options) {
const mutation = { type, payload }
const entry = this._mutations[type]
this._withCommit(() => {
entry.forEach(function commitIterator (handler) {
handler(payload)
})
})
}