当前位置:  首页>> 技术小册>> TypeScript和Vue从入门到精通(五)

16.2.3 Vuex中的Mutation

在Vue.js应用程序中,状态管理是一个至关重要的环节,尤其是当应用变得复杂,包含多个组件且组件间需要共享状态时。Vuex作为Vue.js官方推荐的状态管理模式库,通过集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。在Vuex中,Mutation是实现状态更新的唯一途径,它扮演着核心的角色。本章节将深入探讨Vuex中的Mutation,包括其基本概念、使用方法、最佳实践以及与其他Vuex核心概念的协同工作。

16.2.3.1 Mutation基础

什么是Mutation?

Mutation是Vuex中用于更改状态的同步函数。在Vuex中,所有的状态更新都必须在Mutation中进行,这使得状态的变更更加集中和易于追踪。Mutation接受两个参数:state(当前的状态树)和一个payload(可选的,用于传递额外的信息给Mutation函数)。

为什么需要Mutation?
  • 集中管理状态变更:Mutation确保所有的状态更新都通过预定的函数进行,这有助于开发者更容易地追踪状态的变化。
  • 同步操作:Vuex强制Mutation必须是同步的,这有助于避免复杂的状态变更难以追踪和调试的问题。如果需要执行异步操作,则应该使用Action。
  • 便于追踪和调试:开发者可以利用Vuex的插件(如Vue Devtools)来查看Mutation的调用记录和状态变更历史,从而更容易地调试应用。

16.2.3.2 定义和使用Mutation

定义Mutation

在Vuex的store中,通过mutations属性来定义Mutation。每个Mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。这个回调函数就是我们进行状态更新的地方。

  1. const store = new Vuex.Store({
  2. state: {
  3. count: 0
  4. },
  5. mutations: {
  6. increment(state) {
  7. // 变更状态
  8. state.count++
  9. },
  10. // 带有payload的Mutation
  11. incrementBy(state, payload) {
  12. state.count += payload.amount
  13. }
  14. }
  15. })
触发Mutation

在Vue组件中,可以使用this.$store.commit方法来触发Mutation。commit方法的第一个参数是Mutation的类型(即上面定义的字符串事件类型),第二个参数是传递给Mutation的payload(可选)。

  1. <template>
  2. <div>
  3. <p>{{ count }}</p>
  4. <button @click="increment">Increment</button>
  5. <button @click="incrementBy(5)">Increment by 5</button>
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. computed: {
  11. count() {
  12. return this.$store.state.count;
  13. }
  14. },
  15. methods: {
  16. increment() {
  17. this.$store.commit('increment');
  18. },
  19. incrementBy(amount) {
  20. this.$store.commit('incrementBy', { amount });
  21. }
  22. }
  23. }
  24. </script>

16.2.3.3 Mutation的最佳实践

1. 保持Mutation的纯净性

Mutation应该是纯净的,即它们不应该依赖于或改变除了它们自己的参数以外的任何东西。这意味着它们不应该执行任何异步操作或依赖于外部状态。

2. 使用常量替代字符串类型

将Mutation的类型定义为常量而非字符串,可以避免因拼写错误导致的问题,并使代码更加清晰和易于维护。

  1. // mutation-types.js
  2. export const INCREMENT = 'INCREMENT';
  3. export const INCREMENT_BY = 'INCREMENT_BY';
  4. // store.js
  5. import Vue from 'vue';
  6. import Vuex from 'vuex';
  7. import { INCREMENT, INCREMENT_BY } from './mutation-types';
  8. Vue.use(Vuex);
  9. export default new Vuex.Store({
  10. // ...
  11. mutations: {
  12. [INCREMENT](state) {
  13. state.count++;
  14. },
  15. [INCREMENT_BY](state, payload) {
  16. state.count += payload.amount;
  17. }
  18. }
  19. });
3. 组件中通过映射辅助函数简化代码

在组件中,可以通过Vuex提供的映射辅助函数(如mapMutations)来简化commit的调用。

  1. <script>
  2. import { mapMutations } from 'vuex';
  3. export default {
  4. computed: {
  5. // ...
  6. },
  7. methods: {
  8. ...mapMutations([
  9. 'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
  10. 'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
  11. ])
  12. }
  13. }
  14. </script>

16.2.3.4 Mutation与Action的协同工作

虽然Mutation用于同步地更改状态,但在实际开发中,我们经常会遇到需要执行异步操作来更新状态的情况。这时,就需要用到Action。Action可以包含任意异步操作,并且可以提交(commit)一个或多个Mutation来更新状态。

  1. const store = new Vuex.Store({
  2. // ...
  3. mutations: {
  4. // ...
  5. },
  6. actions: {
  7. incrementAsync({ commit }) {
  8. setTimeout(() => {
  9. commit('increment');
  10. }, 1000);
  11. }
  12. }
  13. })
  14. // 在组件中
  15. this.$store.dispatch('incrementAsync'); // 调用action来异步更新状态

Action通过提交Mutation来更新状态,这种设计保证了状态变更的同步性和可追踪性,同时提供了执行异步操作的能力。

16.2.3.5 总结

Mutation是Vuex中状态更新的核心机制,它通过同步函数的形式集中管理状态的变更,使得状态的变化更加可预测和易于追踪。在定义和使用Mutation时,应遵循最佳实践,如保持Mutation的纯净性、使用常量替代字符串类型以及通过映射辅助函数简化代码。同时,理解Mutation与Action的协同工作机制,可以帮助我们更好地构建复杂且可维护的Vue.js应用。通过合理利用Vuex提供的功能,我们可以构建出高效、可扩展且易于维护的状态管理方案。


该分类下的相关小册推荐: