操作
操作类似于 Mutation,区别在于
- 操作不会直接修改状态,而是提交 Mutation。
- 操作可以包含任意异步操作。
让我们注册一个简单的操作
const store = createStore({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
操作处理程序接收一个上下文对象,该对象公开 store 实例上的相同方法/属性集,因此您可以调用 context.commit
提交 Mutation,或通过 context.state
和 context.getters
访问状态和 Getter。我们甚至可以使用 context.dispatch
调用其他操作。当我们稍后介绍 模块 时,我们将看到为什么此上下文对象本身不是 store 实例。
在实践中,我们经常使用 ES2015 参数解构 来简化代码(尤其是在我们需要多次调用 commit
时)
actions: {
increment ({ commit }) {
commit('increment')
}
}
分发操作
操作使用 store.dispatch
方法触发
store.dispatch('increment')
乍一看这可能很奇怪:如果我们想增加计数,为什么不直接调用 store.commit('increment')
?请记住,**Mutation 必须是同步的**。操作则不是。我们可以在操作中执行**异步**操作
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
操作支持相同的有效负载格式和对象样式分发
// dispatch with a payload
store.dispatch('incrementAsync', {
amount: 10
})
// dispatch with an object
store.dispatch({
type: 'incrementAsync',
amount: 10
})
一个更实用的真实世界操作示例将是结账购物车的操作,这涉及**调用异步 API** 和**提交多个 Mutation**
actions: {
checkout ({ commit, state }, products) {
// save the items currently in the cart
const savedCartItems = [...state.cart.added]
// send out checkout request, and optimistically
// clear the cart
commit(types.CHECKOUT_REQUEST)
// the shop API accepts a success callback and a failure callback
shop.buyProducts(
products,
// handle success
() => commit(types.CHECKOUT_SUCCESS),
// handle failure
() => commit(types.CHECKOUT_FAILURE, savedCartItems)
)
}
}
请注意,我们正在执行异步操作流,并通过提交它们来记录操作的副作用(状态 Mutation)。
在组件中分发操作
您可以在组件中使用 this.$store.dispatch('xxx')
分发操作,或者使用 mapActions
辅助函数,该函数将组件方法映射到 store.dispatch
调用(需要根 store
注入)
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // map `this.increment()` to `this.$store.dispatch('increment')`
// `mapActions` also supports payloads:
'incrementBy' // map `this.incrementBy(amount)` to `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // map `this.add()` to `this.$store.dispatch('increment')`
})
}
}
组合操作
操作通常是异步的,那么我们如何知道操作何时完成?更重要的是,我们如何将多个操作组合在一起以处理更复杂的异步流?
首先要知道的是,store.dispatch
可以处理由触发的操作处理程序返回的 Promise,它也返回 Promise
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
现在您可以这样做
store.dispatch('actionA').then(() => {
// ...
})
以及在另一个操作中
actions: {
// ...
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
}
}
最后,如果我们使用 async / await,我们可以像这样组合我们的操作
// assuming `getData()` and `getOtherData()` return Promises
actions: {
async actionA ({ commit }) {
commit('gotData', await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // wait for `actionA` to finish
commit('gotOtherData', await getOtherData())
}
}
store.dispatch
可以触发不同模块中的多个操作处理程序。在这种情况下,返回值将是一个 Promise,当所有触发的处理程序都已解析时,它将解析。