深入理解 Vuex:从基础到应用场景

cover

前言

在之前的文章中,我们已经对 Vue.js 有了一定的了解。今天我们要对Vue官方的状态共享管理器Vuex进行详细讲解,将其基本吃透,目标是面对大多数业务需求;

一、介绍

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 随着 Vue 一同开发,并且是 Vue.js 官方维护的状态管理库。

在 Vue.js 应用程序中,组件之间的通信是通过 props 和事件来实现的,这种方式在组件层级较浅()的情况下可以很好地管理状态,但是随着应用规模的增长,状态的管理会变得复杂和困难。这时候就需要使用 Vuex 来解决状态管理的问题。

Vuex 中包含以下核心概念:

  • State(状态): 即存储在 Vuex 中的数据,它代表了整个应用的状态。
  • Getter(获取器): 用于从状态树state中派生出一些状态,类似于计算属性
  • Mutation(变更): 是唯一允许修改 Vuex 中状态的地方,但是必须是同步函数。
  • Action(动作): 用于提交 mutation,而不是直接变更状态。可以包含任意异步操作。

二、Vuex的适用范围

Vuex 适用于中大型的 Vue.js 应用程序,特别是当应用的状态变得复杂且需要在多个组件之间共享时。它提供了一种集中式管理状态的方式,使得状态管理变得更加可预测和可维护。
Vuex既适用于Vue2,也适用于Vue3;

当应用中包含以下情况时,考虑使用 Vuex:

  • 多个组件需要共享同一状态。
  • 多个视图依赖于同一状态。
  • 有大量的组件需要访问和修改状态。

当应用程序的状态变得较简单或者组件之间的状态传递并不频繁时,可能并不需要使用 Vuex。在这种情况下,可以考虑使用 Vue.js 的局部状态(data)来管理组件的状态。

三、Vuex的主要组成部分

Vuex 的核心包含四个主要部分:StateGettersMutationsActions

1.State

State 是 Vuex 存储数据的地方,它类似于组件中的 data。State 中的数据可以通过 this.$store.state 访问。

①在根Vuex中定义state
state: {
    message: 'Hello, Vuex!', // 字符串类型变量
    count: 0, // 数字类型变量
    isActive: false, // 布尔类型变量
    user: { // 对象类型变量
      name: 'John Doe',
      age: 30
    },
    items: ['apple', 'banana', 'orange'], // 数组类型变量
    currentDate: new Date() // 引用类型变量
  }

②在 Vuex 中定义模块的 state:

// Module A
const moduleA = {
  state: {
    message: 'Hello from Module A',
    count: 0
  }
};

// Module B
const moduleB = {
  state: {
    message: 'Hello from Module B',
    isActive: true
  }
};

// Vuex Store
const store = new Vuex.Store({
  modules: {
    moduleA,
    moduleB
  }
});

在这个示例中,我们定义了两个模块 moduleAmoduleB,每个模块都有自己的 state 对象,包含了不同的状态属性。
以下是两种在组件中使用 Vuex state 的案例:

①根Vuex直接访问 $store.state:
<template>
  <div>
    <p>Message: {{ $store.state.message }}</p>
    <p>Count: {{ $store.state.count }}</p>
    <p>Active: {{ $store.state.isActive }}</p>
    <p>User: {{ $store.state.user.name }} ({{ $store.state.user.age }})</p>
    <p>Items: {{ $store.state.items }}</p>
    <p>Current Date: {{ $store.state.currentDate }}</p>
  </div>
</template>

特点:

  • 直接访问 $store.state 可以在模板中直接使用 Vuex store 中的 state,语法简单直接。
  • 在模板中使用 $store.state 可能会导致代码冗长,难以维护,尤其是在大型应用中。

② 根Vuex使用 mapState 辅助函数:

<template>
  <div>
    <p>Message: {{ message }}</p>
    <p>Count: {{ count }}</p>
    <p>Active: {{ isActive }}</p>
    <p>User: {{ user.name }} ({{ user.age }})</p>
    <p>Items: {{ items }}</p>
    <p>Current Date: {{ currentDate }}</p>
  </div>
</template>

<script>
import { mapState } from 'vuex';

export default {
  computed: {
    ...mapState([
      'message',
      'count',
      'isActive',
      'user',
      'items',
      'currentDate'
    ]) // 传入数组
  }
};
</script>

特点:

  • 使用 mapState 可以将 Vuex store 中的 state 映射到组件的计算属性中,使得在模板中可以直接使用这些计算属性,映射在计算属性中才能保证实时响应。
  • 使用 mapState 可以简化模板中对 Vuex state 的访问,提高代码的可读性和可维护性。
  • mapState 需要传入一个数组或对象作为参数,这个参数包含了需要映射的 state 属性,这样可以灵活地选择需要的属性映射到组件中。
③直接访问模块 $store.state
<template>
  <div>
    <p>Message from Module A: {{ $store.state.moduleA.message }}</p>
    <p>Count from Module A: {{ $store.state.moduleA.count }}</p>
    <p>Message from Module B: {{ $store.state.moduleB.message }}</p>
    <p>isActive from Module B: {{ $store.state.moduleB.isActive }}</p>
  </div>
</template>

④模块state使用 mapState 辅助函数

<template>
  <div>
    <p>Message from Module A: {{ moduleA_message }}</p>
    <p>Count from Module A: {{ moduleA_count }}</p>
    <p>Message from Module B: {{ moduleB_message }}</p>
    <p>isActive from Module B: {{ moduleB_isActive }}</p>
  </div>
</template>

<script>
import { mapState } from 'vuex';

export default {
  computed: {
    ...mapState('moduleA', [ // 模块名
      'message as moduleA_message', // 使用别名来避免与全局变量冲突
      'count as moduleA_count' // count是原名,moduleA_count是别名
    ]),
    ...mapState('moduleB', [
      'message as moduleB_message',
      'isActive as moduleB_isActive'
    ])
  }
};
</script>
⑤用mapState函数的对象形式映射模块状态

在模板中,你可以直接使用这两个计算属性来获取模块 A 和模块 B 中的 message 状态。下面是模板中如何使用这两个计算属性的示例:

<template>
  <div>
    <p>Message from Module A: {{ moduleA_message }}</p>
    <p>Message from Module B: {{ moduleB_message }}</p>
  </div>
</template>

<script>
import { mapState } from 'vuex';

export default {
  computed: {
    ...mapState({
      // 使用命名空间来映射模块中的状态
      moduleA_message: state => state.moduleA.message, // 模块A下的message对象,别名为moduleA_message
      moduleB_message: state => state.moduleB.message // moduleA_message可以用引号括住,也可以不要引号
    })
  }
};
</script>

在这个案例中,我们展示了五种使用 的 state 的方式。基于模块创建的state使用和基于根Vuex的state使用;

2.Getter

①定义

Getter 允许我们在Vuex中派生状态,它类似于组件中的 computed 属性。Getter 可以接收 state 作为参数,然后返回派生出的状态。

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: 'Todo 1', done: true },
      { id: 2, text: 'Todo 2', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done);
    }
  }
});

在 Vuex 中,Getter 可以用来对 store 中的 state 进行一些计算或筛选,从而得到我们想要的状态,而不需要直接修改原始的 state。这样做有几个好处:

  • 组件中的状态派生: Getter 可以用来将 store 中的状态进行处理,然后在组件中直接使用这些派生出的状态,而无需在组件中进行复杂的计算逻辑。
  • 避免直接修改 state: 使用 Getter 可以避免直接修改 store 中的 state,使得代码更加可维护和可测试,同时也保证了 Vuex 的单向数据流。
  • 重用性和可组合性: 可以将 Getter 进行组合和重用,使得代码更加灵活和可扩展。
②组合性和复用性

在上面的示例中,我们定义了一个名为 doneTodosGetter,它接收 store 中的 state 作为参数,然后返回一个数组,这个数组包含了所有已完成的 todo。在组件中可以直接使用 doneTodos 这个 Getter 来获取已完成的 todo,而无需在组件中手动筛选 todo 数组。这样可以使得组件中的代码更加简洁和清晰。
对于第三点的复用性和组合性,案例如下:

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: 'Todo 1', done: true },
      { id: 2, text: 'Todo 2', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done);
    },
    undoneTodos: state => {
      return state.todos.filter(todo => !todo.done);
    },
    totalTodosCount: state => {
      return state.todos.length;
    },
    undoneTodosCount: (state, getters) => {
      return getters.doneTodos.length; // undoneTodosCount Getter 使用了 doneTodos Getter 来获取所有已完成的任务
    }
  }
});
③模块间的 Getter 访问

在 Vuex 中,一个模块的 Getter 可以访问其他模块的 state 和 Getter,以及根模块的 state 和 Getter。这是因为在 Getter 中,可以通过参数访问当前模块的 state 和 Getter,以及 rootState 和 rootGetters。同理Vuex根getters也可以访问其他模块的state和getters;案例代码如下:

const store = new Vuex.Store({
  modules: {
    moduleA: {
      state: {
        message: 'Module A Message'
      },
      getters: {
        moduleA_message: state => state.message
      }
    },
    moduleB: {
      state: {
        message: 'Module B Message'
      },
      getters: {
        moduleB_message: state => state.message
      }
    },
    moduleC: {
      getters: {
        combinedMessages: (state, getters, rootState, rootGetters) => {
          const moduleA_message = rootGetters['moduleA/moduleA_message'];
          const moduleB_message = rootGetters['moduleB/moduleB_message'];
          return `${moduleA_message} - ${moduleB_message}`;
        }
      }
    }
  }
});
const store = new Vuex.Store({
  modules: {
    moduleA: {
      state: {
        message: 'Module A Message'
      },
      getters: {
        moduleA_message: state => state.message
      }
    }
  },
  getters: {
    moduleA_message: (state, rootGetters) => {
      return rootGetters['moduleA/moduleA_message'];
    }
  }
});

从这个角度看,rootGetters是一个对象,其中每个键代表每个模块名称,值为每个模块对于的getter
同理rootState.moduleName.stateName可以访问不同模块间的state属性;

④缓存特性

Getter 在默认情况下是具有缓存特性的,意味着在相同的状态下多次调用相同的 Getter,只会计算一次,并且在下次调用时直接返回缓存的结果,而不会重新计算。这可以提高性能,避免重复计算

Vuex 中,Getter 是一个函数,可以接收 stategettersrootState 作为参数。这使得 Getter 具有更大的灵活性, 由于 Getter 是函数,因此可以在其中进行条件判断和计算,根据不同的情况返回不同的值,从而实现更灵活的状态派生和计算逻辑;

3. Mutations

①定义

Mutations 是 Vuex 中用来唯一能修改状态的函数,类似于组件中的 methods。Mutation 函数接收当前状态 (state) 作为第一个参数,并且可以接收额外的参数作为需要修改的数据。Mutation 必须是同步函数,不能包含异步操作。

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    },
    decrement(state) {
      state.count--;
    },
    incrementBy(state, payload) {
      state.count += payload.amount;
    }
  }
});
  • Mutations 是同步的:Mutations 中的操作是同步执行的,不支持异步操作。
  • 只能通过 Mutations 修改状态:在 Vuex 中,强制规定只能通过 Mutations 来修改状态,这样可以更好地追踪状态的变化,并且使得状态变更更加可控。
②在组件中使用
methods: {
  increment() {
    this.$store.commit('increment');
  },
  decrement() {
    this.$store.commit('decrement');
  },
  incrementBy(amount) {
    this.$store.commit('incrementBy', { amount }); // this指的是Vue实例,第二个参数等于{ amount: amount }
  }
}
③应用场景
  • 修改单个状态:当需要修改 Vuex 中的某个单个状态时,可以使用 Mutation。
  • 批量修改状态:可以一次性修改多个状态,保持状态变更的原子性。
  • 追踪状态变化:通过 Mutation,可以清晰地追踪状态的变化,便于调试和排查问题。
    下面是应用场景2的一个案例:
const store = new Vuex.Store({
  state: {
    count: 0,
    message: 'Hello, Vuex!'
  },
  mutations: {
    updateState(state, payload) {
      // payload 是一个包含多个状态的对象
      Object.assign(state, payload);
    }
  },
  actions: {
    updateState(context, payload) {
      context.commit('updateState', payload);
    }
  }
});

// 在组件中调用这个 Mutation 来批量修改状态
this.$store.commit('updateState', {  // 如果是模块,则this.$store.commit('moduleName/mutationName', payload)
  count: 10,
  message: 'Hello, Vuex! Updated!'
});

Object.assign(state, payload);是浅拷贝方法,因此组件中这样使用,可能会导致整个模块或者全局都改变!

4. Actions

①定义

Action 类似于 Mutation,但具有异步操作的能力;它提交的是 Mutation,而不是直接变更状态。其通过 store.dispatch 触发Mutations 来变更状态。
Actions 接收一个上下文对象 (context),这个context是包含了与 Vuex 实例具有相同方法和属性的对象,例如 statecommitdispatch 等;

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    incrementAsync(context) {
      setTimeout(() => {
        context.commit('increment'); // 变量名为对应mutation名称
      }, 1000);
    }
  }
});

在 Vuex 中,每个模块module内部都有一个上下文对象 (context),它提供了与 根store 实例具有相同方法和属性的对象,包括 state(属性)、commit(方法,提交mutation)、dispatch(方法,分发action触发异步) 等。这样设计的目的是为了让模块内部的 actions、mutations、getters 等能够访问和操作模块的局部状态,而不需要通过全局的 store 对象。

②组件中使用

Actions 可以通过 store.dispatch 方法在组件中触发。在 Action 中,可以执行异步操作,例如发起 HTTP 请求、定时器等,然后在异步操作完成后提交 Mutations 来变更状态

// 组件中触发 Action
methods: {
  incrementAsync() {
    this.$store.dispatch('incrementAsync');
  }
}
③特点
  • 异步操作:Actions 可以执行任意异步操作,例如 HTTP 请求、定时器等。
  • 提交 Mutations:Actions 通过 context.commit 来提交 Mutations,从而变更状态。
  • 触发方式:Actions 可以通过 store.dispatch 方法在组件中触发。
④应用场景
  • 处理异步逻辑:例如发起 HTTP 请求获取数据后提交 Mutations 更新状态。
  • 封装复杂逻辑:将复杂的业务逻辑封装在 Action 中,使组件更加简洁。
  • 异步操作:Actions 可以执行异步操作,但应该避免在 Action 中进行直接的状态变更。
  • 触发方式:Actions 必须通过 store.dispatch 方法来触发。保证顺序执行和稳定;
⑤WebGIS中的应用场景
  • 异步数据获取: 在 WebGIS 应用中,通常需要从服务器获取地理空间数据、地图瓦片、地图图层配置等信息。Actions 可以用于发起异步请求,并在数据获取完成后更新 Vuex 中的状态,以便在地图中显示数据。
  • 用户交互和事件处理: 用户在地图上的操作通常会触发一系列的事件,例如点击地图、拖动地图、放大缩小地图等。Actions 可以用于监听这些事件,并根据用户的操作进行相应的状态更新或地图操作。
  • 状态管理: WebGIS 应用中通常包含复杂的地图状态,例如地图的视图范围、图层的可见性、图层样式等。Actions 可以用于管理这些状态,并在需要时进行状态的更新和同步。
  • 地图操作和交互效果: Actions 可以用于执行地图操作,例如平移地图、缩放地图、绘制图形等,并根据操作结果更新地图的状态和展示效果。
  • 应用配置和设置: Actions 可以用于处理应用的配置信息和用户设置,例如地图的初始配置、图层的加载顺序、应用的主题设置等。

四、Vuex的常用函数

1.mapState:

mapState 函数用于将 Vuex 中的 state 映射为组件的计算属性。它接收一个数组或对象作为参数,数组中可以是 state 中的属性名,也可以是对象形式,对象的键是组件中的属性名,值是 state 中的属性名或者是一个返回状态的函数。这样,在组件中就可以直接使用这些计算属性,无需再通过 $store.state.xxx 的方式访问 Vuex 中的状态。

import { mapState } from 'vuex';

export default {
  computed: {
    // 使用数组
    ...mapState(['count', 'message']),
    
    // 使用对象
    ...mapState({
      user: state => state.userInfo,
      isLoggedIn: state => state.auth.isLoggedIn
    })
  }
};

2.mapGetters:

mapGetters 函数用于将 Vuex 中的 getters 映射为组件的计算属性。它接收一个数组或对象作为参数,用法与 mapState 相似,可以使用数组形式或者对象形式来进行映射。

import { mapGetters } from 'vuex';

export default {
  computed: {
    ...mapGetters(['doneTodosCount', 'undoneTodosCount']),

    ...mapGetters({
      formattedMessage: 'formattedMessage'
    })
  }
};

3.mapMutations:

mapMutations 函数用于将 Vuex 中的 mutations 映射为组件的方法。它接收一个数组或对象作为参数,数组中是 mutations 中的方法名,对象形式的键是组件中的方法名,值是 mutations 中的方法名。

import { mapMutations } from 'vuex';

export default {
  methods: {
    ...mapMutations(['increment', 'decrement']),

    ...mapMutations({
      setUserName: 'SET_USER_NAME'
    })
  }
};

数组方法直接用,对象方法可以改别名后使用

...mapMutations(['increment', 'decrement']) 等价于以下代码:

{
  increment: function() {
    return this.$store.commit('increment');
  },
  decrement: function() {
    return this.$store.commit('decrement');
  }
}

它将 mapMutations 返回的对象展开,将其中的每个方法映射到组件中,使得用户可以直接调用 this.increment()this.decrement() 来提交对应的 mutations

4.mapActions:

mapActions 函数用于将 Vuex 中的 actions 映射为组件的方法。用法与 mapMutations 类似,接收一个数组或对象作为参数,数组中是 actions 中的方法名,对象形式的键是组件中的方法名,值是 actions 中的方法名。

import { mapActions } from 'vuex';

export default {
  methods: {
    ...mapActions(['login', 'logout']),

    ...mapActions({
      fetchUserData: 'FETCH_USER_DATA'
    })
  }
};

通常情况下,mutation 用于同步地修改状态,而 actions 则用于包含异步操作的场景。在 actions 中可以调用多个 mutation 来修改状态,但通常不会在 actions 中定义不需要通过 mutation 修改状态的独立方法。这样可以保持状态变更的可追踪性和可维护性。

当在 actions 中执行异步操作时,可能需要在异步操作完成后修改多个状态。例如,假设有一个购物车功能,需要在用户点击结账按钮时执行以下操作:

  1. 清空购物车中的商品列表。
  2. 将商品列表中的商品添加到订单列表中。
  3. 将订单总金额清零。

在这种情况下,可以在 actions 中调用多个 mutation 来修改这些状态。以下是示例代码:

const store = new Vuex.Store({
  state: {
    cart: [
      { id: 1, name: 'Product 1', price: 10 },
      { id: 2, name: 'Product 2', price: 20 },
      // 其他商品
    ],
    orders: [],
  },
  getters: {
    totalAmount: state => {
      return state.cart.reduce((total, product) => total + product.price, 0); // 累加,p1为累加器,p2为当前元素,0为初始值
    }
  },
  mutations: {
    clearCart(state) {
      state.cart = [];
    },
    addToOrders(state, products) {
      state.orders.push(...products);
    },
    resetTotalAmount(state) {
      state.totalAmount = 0;
    }
  },
  actions: {
    checkout({ commit, state }) {
      // 模拟异步操作,例如向后端发送订单请求
      setTimeout(() => {
        // 异步操作完成后,调用多个 mutation 来修改状态
        commit('addToOrders', state.cart); // 添加到订单
        commit('clearCart'); // 清空购物车
        commit('resetTotalAmount'); //清空总额
      }, 1000);
    }
  }
});

在上面的示例中,checkout action 执行了一系列异步操作,然后调用了多个 mutation 来修改状态。

五、Vuex的应用场景

1.管理购物车状态:

  • 应用场景:在线商城中,用户可以将商品加入购物车,修改商品数量或移除商品。
  • 实现方式:使用 Vuex 来管理购物车的状态,包括购物车中的商品列表、商品数量、总价等信息。通过 mutations 修改购物车状态,例如增加商品、删除商品、修改商品数量等操作。

2.用户认证状态管理:

  • 应用场景:网站或应用中需要对用户进行认证,登录后可以访问特定的页面或功能,未登录状态下需要跳转到登录页面。
  • 实现方式:使用 Vuex 存储用户的认证状态,例如用户信息、登录状态、权限等信息。通过 mutations 修改用户认证状态,例如登录、注销、更新用户信息等操作。在需要认证的页面或功能中,通过 getters 获取用户的认证状态来控制页面展示逻辑。

3.表单数据管理:

  • 应用场景:页面中存在复杂的表单,包含多个输入框、复选框、下拉框等元素,需要实时根据用户输入更新表单数据。
  • 实现方式:使用 Vuex 存储表单的状态,例如表单数据、验证状态、提交状态等信息。通过 mutations 修改表单数据状态,例如更新输入框值、切换复选框状态等操作。通过 getters 获取表单数据状态,实时展示给用户,同时通过 actions 处理表单提交逻辑,例如表单验证、数据提交等操作。

4.页面之间共享的数据状态:

  • 应用场景:不同页面或组件之间需要共享相同的数据状态,例如全局的主题设置、语言设置等。
  • 实现方式:使用 Vuex 存储全局的数据状态,例如主题颜色、语言设置等信息。通过 mutations 修改全局数据状态,例如切换主题、切换语言等操作。通过 getters 获取全局数据状态,实时应用到页面或组件中。

5.WebGIS中的应用场景

在 WebGIS 中,Vuex 可以应用于许多场景,以管理地图状态、图层数据、用户交互等。以下是一些常见的 WebGIS 应用场景:

1.地图状态管理:
  • 应用场景:在 WebGIS 应用中,用户可能会对地图进行缩放、平移、旋转等操作,这些操作会导致地图状态的变化,如当前的中心点、缩放级别、旋转角度等。
  • 实现方式:使用 Vuex 存储地图的状态信息,例如中心点坐标、缩放级别、旋转角度等。通过 mutations 修改地图状态,例如更新中心点坐标、修改缩放级别等操作。通过 getters 获取地图状态信息,以便在地图组件中实时展示。
2.图层数据管理:
  • 应用场景:WebGIS 应用中通常包含多个图层,如矢量图层、栅格图层、图像图层等,这些图层可能需要根据用户的操作进行显示、隐藏、更新等操作。
  • 实现方式:使用 Vuex 存储图层的状态信息,例如图层的可见性、透明度、样式等。通过 mutations 修改图层状态,例如显示/隐藏图层、更新图层样式等操作。通过 getters 获取图层状态信息,以便在地图组件中实时控制图层的显示。
3.用户交互管理:
  • 应用场景:WebGIS 应用中用户可能会进行交互操作,如点击地图、绘制要素、查询信息等,这些操作需要及时响应并更新相关状态。
  • 实现方式:使用 Vuex 存储用户交互的状态信息,例如点击的位置、绘制的要素、查询到的信息等。通过 mutations 修改用户交互状态,例如记录点击位置、绘制要素、查询结果等操作。通过 getters 获取用户交互状态信息,以便在地图组件中实时展示用户的操作。

六、Vuex的最佳实践思路

针对一个中大型WebGIS项目,可以采用以下方法论来设计和组织 Vuex 的解决方案:

  1. 模块化设计
    ○ 将 Vuex store 拆分成多个模块,每个模块专注于处理特定的业务逻辑或状态管理。
    ○ 根据业务领域的不同,可以将模块划分为地图模块、用户模块、数据模块等,每个模块管理对应领域的状态和逻辑。
  2. 命名空间
    ○ 在定义 Vuex 模块时,可以使用命名空间来避免不同模块之间的命名冲突,确保模块的状态和操作的唯一性和可识别性。
    ○ 通过在模块定义时设置 namespaced: true 来启用命名空间。
  3. 拆分状态
    ○ 将 Vuex store 中的状态拆分成不同的模块级别的状态,每个模块负责管理自己的状态。
    ○ 例如,地图模块可以管理地图状态(中心点坐标、缩放级别等)、图层状态等,用户模块可以管理用户信息、权限状态等。
  4. 常量管理
    ○ 使用常量来表示 mutation 和 action 的名称,以提高代码的可读性和维护性。
    ○ 将常量集中管理,可以在单独的文件中定义常量,并在需要使用的地方引入,避免重复定义和错误拼写。
  5. 异步操作
    ○ 对于需要进行异步操作的情况,例如 API 请求、数据加载等,使用异步 action 来处理。
    ○ 在异步 action 中进行异步操作,并在操作完成后提交 mutation 来更新状态,保持 Vuex 单向数据流的规范。
  6. 模块间通信
    ○ 对于模块之间需要进行通信的情况,可以通过根模块来协调不同模块之间的状态和操作。
    ○ 使用根模块的 state 和 getters 来访问和管理不同模块的状态,使用根模块的 mutations 和 actions 来触发和处理模块间的操作。
  7. 代码组织
    ○ 合理组织 Vuex 相关的代码结构,例如将常量、mutations、actions、getters 等分别放置在不同的文件中,便于管理和维护。
    ○ 可以按照功能模块或业务领域来组织代码结构,使代码清晰易读。

七、总结

在本文中,我们全面地探讨了 Vuex,这是一个专为 Vue.js 应用程序开发的状态管理模式。通过学习 Vuex 的基础概念、高级用法、辅助函数和应用场景,我们深入理解了 Vuex 的工作原理和应用方法。

通Vuex 提供了一种统一的状态管理方案,使得不同组件之间可以轻松共享状态,并且保证状态的一致性。
在实际项目中,我们可以利用 Vuex 来管理购物车状态、用户认证状态、表单数据状态等。通过合理地设计和使用 Vuex,我们可以有效地管理复杂的状态逻辑,并且提高项目的开发效率和质量。

文章参考

  • 开始 | Vuex:

  • vuex的超详细讲解和具体使用细节记录(篇幅略长,建议收藏) - 知乎

  • Vuex的全面简约版总结_vuex参考文献-CSDN博客

项目地址

  • Github地址
  • 拓展阅读

如果觉得我的文章对您有帮助,三连+关注便是对我创作的最大鼓励!或者一个star🌟也可以😂.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/453321.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Power Apps】响应式布局与布局容器

做响应式布局之前要先把这里关掉呦。 这里我可能要先简单说一下什么是响应式布局&#xff0c;说白了就是咱们做出来的应用的界面可以根据当前窗口的大小来自适应地调整内部组件的大小、位置等属性&#xff0c;这样我们只需要做一套页面&#xff0c;就可以既在桌面端使用&#x…

linux-MDK can电机带导轨

确保接线正确&#xff0c;这个带导轨的电机需要24V的电压 $ ls /dev //查看端口是什么$ sudo slcand -o -s6 /dev/ttyACM0 can0 //将端口封装为can0 $ sudo ip link set can0 up //打开端口 按照电机说明书&#xff0c;按照需要的指令计算检验和&#xf…

【C语言】tcp_transmit_skb

一、__tcp_transmit_skb讲解 这个函数 __tcp_transmit_skb() 是 Linux 内核中 TCP/IP 协议栈的一部分&#xff0c;负责处理传输控制协议&#xff08;TCP&#xff09;数据包的发送。具体来说&#xff0c;这个函数将 TCP 头部添加到一个没有任何头部信息的 socket buffer (sk_bu…

食药物质创新 赋能中式滋补健康产业发展交流会圆满结束

3月5日&#xff0c;“食药物质创新 赋能中式滋补健康产业发展交流会”在山东国际会展中心召开。本次会议由中国生物发酵产业协会主办&#xff0c;浙江科技大学、未名太研生物科技(绍兴)有限公司承办&#xff0c;汇乐达供应链服务(常州)有限责任公司支持。本次论坛旨在加强行业创…

C语言--从零开始的扫雷游戏

C语言--从零开始的扫雷游戏 1. 游戏说明2. 总体代码3. 详细讲解3.1 菜单部分3.2 游戏主体部分3.2.1 总体分析3.2.2 棋盘初始化3.2.3 棋盘展示3.2.4 设置地雷3.2.5 扫雷阶段3.2.6 统计雷个数的代码3.2.7 使用迭代的方式进行展开&#xff1a;3.2.8 扫雷部分主体代码 4. 总结 1. 游…

SpringBoot(源码解析 + 实现底层机制)

文章目录 1.搭建SpringBoot底层机制开发环境1.创建maven项目2.使用Git管理项目&#xff08;可以略过&#xff09;1.创建一个github存储库2.克隆到本地&#xff0c;复制文件夹的内容3.粘贴到idea项目文件夹&#xff0c;将其作为本地仓库与远程仓库关联 3.pom.xml 引入父工程和场…

【算法积累】辗转相除法

【算法积累】辗转相除法&#xff0c;python实现两种 辗转相除法&#xff08;又称欧几里得算法&#xff09;减法&#xff08;不常用&#xff09;代码实现执行结果 辗转相除法代码实现执行结果 辗转相除法&#xff08;又称欧几里得算法&#xff09; 又称欧几里得算法&#xff0c…

使用Python将多个pdf指定页整合到一个pdf文件中

在工作的一些场景中&#xff0c;有时需要我们将多个pdf文件中的内容提取出来&#xff0c;比如有10个pdf文件&#xff0c;我们要统一打印pdf文件的第一页或者最后一页… 需求分析 我们需要批量提取PDF文件中的任意一页&#xff0c;可以是第一页也可以是中间某一页&#xff0c;…

【C++算法模板】图的存储-邻接矩阵

文章目录 邻接矩阵洛谷3643 图的存储 邻接矩阵 邻接矩阵相比于上一篇博客邻接表的讲解要简单得多 数据结构&#xff0c;如果将二维数组 g g g 定义为全局变量&#xff0c;那默认初始化应该为 0 0 0 &#xff0c;如果题目中存在自环&#xff0c;可以做特判&#xff0c; m e …

微信小程序云开发教程——墨刀原型工具入门(常用组件)

引言 作为一个小白&#xff0c;小北要怎么在短时间内快速学会微信小程序原型设计&#xff1f; “时间紧&#xff0c;任务重”&#xff0c;这意味着学习时必须把握微信小程序原型设计中的重点、难点&#xff0c;而非面面俱到。 要在短时间内理解、掌握一个工具的使用&#xf…

docker+elasticsearch

一&#xff0c;环境准备&#xff1a;安装docker&#xff08;往期文章&#xff09; 二&#xff0c;elasticsearch简介&#xff1a; 用于储存数据 三&#xff0c;部署&#xff1a; 1&#xff09;&#xff0c;拉取镜像 使用本作者提供的java17镜像 2&#xff09;&#xff0c;…

基于大模型的Agent进行测试评估的3种方案

本文首发于博客 基于大模型的Agent进行测试评估的3种方案 我们都知道当前基于大模型构建的 Agent 能力极不稳定&#xff0c;而今年我司产品又在规划接入 Agent 能力&#xff0c;所以在引入之前&#xff0c;需要先设计一套测试框架&#xff0c;来看看各种场景下容错率是否能达…

Linux 基本命令

文章目录 1.echo2.cd3.find4.mkdir5.cp6.rm7.wc8.tar9.tail10.vim11.grep12.sed13 touch14 ls15 快捷键16 ln17 mv18 useradd19 usermod20 su 每天一个Linux命令 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 1.echo 中文 (Chinese): “回声” 或 “输…

分布式链路追踪(一)SkyWalking(2)使用

一、使用方法 1、简介 agent探针可以让我们不修改代码的情况下&#xff0c;对Java应用上使用到的组件进行动态监控&#xff0c;获取运行数据发送到OAP上进行统计和存储。agent探针在Java使用中是使用Java agent技术实现。不需要更改任何代码&#xff0c;Java agent会通过虚拟…

Linux虚拟机安装Qt步骤记录

(一&#xff09;安装命令&#xff0c;按照网上的教程&#xff0c;亲测可行 在终端中依次输入以下命令&#xff0c; 1.更新软件源列表&#xff1a; sudo apt-get update 2.安装Qt开发工具包,windows上我用的是Qt6,根据网上也是初次在Linux上安装Qt,安装版本5应该问题不大&…

智慧农业新篇章:DSSAT模型、APSIM模型、WOFOST与PCSE模型综合应用,引领作物生长模拟与产量预测新潮流

目录 ★WOFOST模型与PCSE模型应用 ★基于R语言APSIM模型进阶应用与参数优化、批量模拟 ★最新DSSAT作物模型建模方法及应用 ★基于Python语言快速批量运行DSSAT模型及交叉融合、扩展应用 ★R语言与作物模型&#xff08;以DSSAT模型为例&#xff09;融合应用 ★遥感数据与…

论文阅读——VSA

VSA: Learning Varied-Size Window Attention in Vision Transformers 方法&#xff1a; 给定输入特征X&#xff0c;VSA首先按照基线方法的例程&#xff0c;将这些标记划分为几个窗口Xw&#xff0c;窗口大小为预定义的w。我们将这些窗口称为默认窗口&#xff0c;并从默认窗口中…

KMP算法——解决字符串匹配问题

一般来说在你没学过KMP算法前&#xff0c;你解决字符串匹配问题会采用BF算法——BF算法&#xff0c;即暴力(Brute Force)算法&#xff0c;是普通的模式匹配算法&#xff0c;BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配&#xff0c;若相等&#xff0c;…

BM1684X搭建sophon c++环境

1:首先安装编译好sophon-sail 比特大陆BM1684X开发环境搭建--SOC mode-CSDN博客 2:在将之前配置的soc-sdk拷贝一份到sdk根目录&#xff0c;将交叉编译好的sail中的build_soc拷贝至soc-sdk文件夹内&#xff1b; cp -rf build_soc/sophon-sail/inlcude soc-sdk cp -rf build_soc…

YOLOv8独家改进:backbone改进 | TransXNet:聚合全局和局部信息的全新CNN-Transformer视觉主干| CVPR2024

💡💡💡本文独家改进:CVPR2024 TransXNet助力检测,代替YOLOv8 Backbone 改进结构图如下: 收录 YOLOv8原创自研 https://blog.csdn.net/m0_63774211/category_12511737.html?spm=1001.2014.3001.5482 💡💡💡全网独家首发创新(原创),适合paper !!! 💡…