在前面计数器程序的改写中,我们抛出了一个问题:
调用vuex中的mutation,为什么不是直接store.mutation.xxx
而是要store.commit('xxx')来实现
下面就来介绍vuex的又一个核心概念Mutation
更改Vuex-store中状态的唯一方法就是提交mutation
Vuex中mutation类似于事件:
每个mutation都有一个字符串的事件类型(type)和 一个回调函数(handler)
回调函数就是实际进行状态更改的地方,
mutation接受state作为第一个参数:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
// 接受state作为第一个参数:
increment (state) {
// 变更状态
state.count++
}
}
})
我们不能直接调用mutation handler
当触发一个类型为 increment 的 mutation 时,此函数才会被调用
要唤醒一个 mutation handler,需要以相应的 type 调用 store.commit 方法:
store.commit('increment')
还可以使用对象风格的提交方式:
store.commit({
type: 'increment',
amount: 10
})
向store.commit传入额外参数,作为mutation的载荷(payload):
mutations: {
increment (state, n) {
state.count += n
}
}
store.commit('increment', 10)
载荷可以是一个能包含多个字段的对象,使mutations更易读:
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
store.commit('increment', {
amount: 10
})
对象风格的提交方式:
tore.commit({
type: 'increment',
amount: 10
})
使用对象风格提交方式,整个对象作为载荷传入mutation函数,因此handler保持不变:
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
mutation中事件的命名使用大写的常量类型
将常量放在单独的文件中,让代码合作者对整个app包含的mutation一目了然
mutation-types.js:
export const SOME_MUTATION = 'SOME_MUTATION'
使用常量:
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// ES2015风格的计算属性命名功能,使用常量作为函数名
[SOME_MUTATION] (state) {
// mutate state
}
}
})
在多人协作的大型项目中,使用常量会很有帮助
mutation必须是同步函数
每一条mutation被记录时,devTools都需要捕捉前一状态和后一状态的快照
如果mutation中使用异步函数的回调这不可能完成
因为当mutation触发时,回调函数还未被调用,devtools不知道何时回调函数实际被调用
任何在回调函数中进行的状态的改变都是不可追踪的
在mutation中混合异步调用会导致程序难以调试
当调用两个包含异步回调的mutation来改变状态,哪个先回调是不可预知的,
所以,在Vuex中,mutation必须是同步事务
处理异步操作将由Action负责
将在vuex核心概念Action进行介绍
在组件中可以使用this.$store.commit('xxx')提交mutation
也可以使用mapMutations辅助函数将组件中的methods映射为store.commit调用(需要在根节点注入 store)
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
// 将 `this.increment()` 映射为 `this.$store.commit('increment')`
'increment',
// `mapMutations` 也支持载荷:
// 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
'incrementBy'
]),
...mapMutations({
// 将 `this.add()` 映射为 `this.$store.commit('increment')`
add: 'increment'
})
}
}