ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
>[success] 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation **所有state中数据的修改必须通过提交 mutation的方式** mutation 都有一个字符串的**事件类型 (type)**和 一个**回调函数 (handler)**。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数: ~~~ const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 变更状态 state.count++ } } }) ~~~ 调用**store.commit**方法提交mutation 进行修改 > 这种提交修改的方式类似于事件系统,在mutations中注册事件处理函数,然后使用store.commit()触发事件 ~~~ store.commit('increment') ~~~ > `store.commit()`用来触发`mutations` > `store.dispatch()`用来触发`Action` ## 二:提交负载(参数) 你可以向`store.commit`传入额外的参数,即 mutation 的**载荷(payload)**: ~~~ // ... mutations: { increment (state, n) { state.count += n } } ~~~ ~~~ store.commit('increment', 10) ~~~ 在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读: ~~~ // ... mutations: { increment (state, payload) { state.count += payload.amount } } ~~~ ~~~ store.commit('increment', { amount: 10 }) ~~~ ## **对象风格的提交方式** 提交 mutation 的另一种方式是直接使用包含`type`属性的对象: ~~~ store.commit({ type: 'increment', amount: 10 }) ~~~ 当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数,因此 handler 保持不变: ~~~ mutations: { increment (state, payload) { state.count += payload.amount } } ~~~ ## **使用常量替代 Mutation 事件类型** 使用常量替代 mutation 事件类型在各种 Flux 实现中是很常见的模式。这样可以使 linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个 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 风格的计算属性命名功能来使用一个常量作为函数名 // 等价es5中的mutations[SOME_MUTATION] = function(){} [SOME_MUTATION] (state) { // mutate state } } }) ~~~ 用不用常量取决于你——在需要多人协作的大型项目中,这会很有帮助。但如果你不喜欢,你完全可以不这样做。 ## **Mutation 必须是同步函数** **Mutation必须是同步,因为异步无法跟踪状态的变化,无法知道回调函数什么时候触发,状态什么时候改变,这将会带来调试上的噩梦。 ** ### 在组件中提交 Mutation 你可以在组件中使用`this.$store.commit('xxx')`提交 mutation,或者使用`mapMutations`辅助函数将组件中的 methods 映射为`store.commit`调用(需要在根节点注入`store`)。 ~~~ import { mapMutations } from 'vuex' export default { // ... methods: { ...mapMutations([ 'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')` // `mapMutations` 也支持载荷: 'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)` ]), ...mapMutations({ add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')` }) } } ~~~ ## **下一步:Action** 在 mutation 中混合异步调用会导致你的程序很难调试。例如,当你调用了两个包含异步回调的 mutation 来改变状态,你怎么知道什么时候回调和哪个先回调呢?这就是为什么我们要区分这两个概念。在 Vuex 中,**mutation 都是同步事务**: ~~~ store.commit('increment') // 任何由 "increment" 导致的状态变更都应该在此刻完成。 ~~~