1.什么是actions?(操作mutation)
- 背景:在mutation中我们讲到,mutation中是存放处理数据的方法的集合,我们使用的时候需要commit。但是commit是同步函数,而且只能是同步执行。那我们想一步操作怎么办?
- 作用:在actions中提交mutation,并且可以包含任何的异步操作。actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据(但是还是通过mutation来操作,因为只有它能操作)
2.怎么用actions?
定义actions
:
const store = new Vuex.Store({//创建store实例
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: { //只是提交`commit`了`mutations`里面的方法。
increment (context) {
context.commit('increment')
}
}
})
一般我们会简写成这样
actions: {
increment ({ commit }) {
commit('increment')
}
}
分发actions
:
store.dispatch('increment')
MapActions
和MapState
以及MapMutations
类似。
3.源码分析
registerAction()
:初始化action
,和registerMutation
类似,不同的地方是mutation
是同步的修改当前模块的state
,action
是可以异步的去修改。但是还是通过提交mutation
来修改,必须明白在Vuex中只又mutation
能修改state
。
function registerAction (store, type, handler, path = []) {
const entry = store._actions[type] || (store._actions[type] = [])
//通过types拿到action的对象数组
const { dispatch, commit } = store
entry.push(function wrappedActionHandler (payload, cb) {
//包装action成一个函数,payload表示载荷,并传入一个对象,
let res = handler({
dispatch,
commit,
getters: store.getters,
state: getNestedState(store.state, path),
rootState: store.state
}, payload, cb)
if (!isPromise(res)) {
//如果不是promise对象,就包装成Promise对象,这也就是前面分析store的时候,断言函数要判断是否存在promise。
res = Promise.resolve(res)
}
if (store._devtoolHook) {
return res.catch(err => {
store._devtoolHook.emit('vuex:error', err)
throw err
})
} else {
return res
}
})
}
dispatch(
):分发actions
dispatch (type, payload) {
//判断type是否是对象类型
if (isObject(type) && type.type) {
payload = type
type = type.type
}
const entry = this._actions[type]
if (!entry) {
console.error(`[vuex] unknown action type: ${type}`)
return
}
return entry.length > 1
? Promise.all(entry.map(handler => handler(payload)))
//在 action 的回调函数里,可以拿到当前模块的上下文包括 store 的 commit 和 dispatch 方法、getter、当前模块的 state 和 rootState
: entry[0](payload)
}