深入理解 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_messagemoduleB_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🌟也可以😂.

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

『操作系统OS笔记』MAC(m1芯片)电脑安装FFmpeg

MAC(m1芯片)电脑安装FFmpeg mac电脑安装ffmpeg两种方法 文章目录 1. brew安装FFmpeg2. 官网下载FFmpeg压缩包3. 使用FFmpeg将音频和视频合并 1. brew安装FFmpeg brew install ffmpeg # 需要等比较久的时间&#xff0c;安装很多东西&#xff0c;安装过程中如果遇到报错对应解决…

MES数据采集设备

在智能制造日益盛行的今天&#xff0c;MES&#xff08;制造执行系统&#xff09;作为连接计划与生产现场的关键环节&#xff0c;其重要性不言而喻。而MES数据采集设备则是MES系统的核心组件&#xff0c;负责实时、准确地获取生产现场的各种数据&#xff0c;为企业的生产决策提供…

信息系统项目管理师--范围管理

项⽬范围管理 产品范围&#xff1a;指某项产品、服务或成果所具有的特征和功能。产品范围的完成情况是根据产品需求来衡量的。“需求”是指根据特定协议或其他强制性规范&#xff0c;产品、服务或成果 必须具备的条件或能⼒。 项⽬范围&#xff1a;包括产品范围&#xff0c;是为…

探索HTTP/2

文章目录 http/1.1http/2疑惑 探索1. 连接前言2. 帧结构2.1 帧类型 Type 3. 帧详情3.1 SETTINGS 帧3.2 WINDOW_UPDATE 帧3.3 PRIORITY 帧3.4 HEADERS 帧3.5 DATA 帧3.6 PING3.7 GOAWAY 帧3.8 RST_STREAM 帧3.9 PUSH_PROMISE 帧3.10 CONTINUATION 帧 你对http2了解多少&#xff…

基于 EfficientNetV2 实现判别MNIST 手写模型分类

pytorch深度学习项目实战100例 的学习记录 我的环境&#xff1a; 白票大王&#xff1a; google colab 用其他的话&#xff0c;其实实现也行&#xff0c;但是让小白来重环境来开始安装的话&#xff0c;浪费时间 论文速读 EfficientNetV2是由 Google Research&#xff0c;Br…

华为配置智能升级功能升级设备示例

配置智能升级功能升级设备示例 组网图形 图1 配置智能升级功能组网图 背景信息组网需求配置思路前提条件操作步骤操作结果 背景信息 为了方便用户及时了解设备主流运行版本&#xff0c;快速完成升级修复&#xff0c;华为设备支持自动下载、自助升级功能。用户在设备Web网管…

【HTML】HTML基础7.2(有序列表)

目录 标签 效果 注意 标签 <ol> <li>列表内容</li> <li>列表内容</li> <li>列表内容</li> <li>列表内容</li> 。。。。。。 </ol> 效果 代码 <ol><li>银河护卫队 10000000000</li><l…

C++ LRU缓存

题目&#xff1a; //构建双向链表的节点结构&#xff08;要有两个构造函数&#xff09; struct Node{int key, val;Node* pre;Node* next;Node():key(0), val(0), pre(nullptr), next(nullptr) {}Node(int _key, int _val): key(_key), val(_val), pre(nullptr), next(nullpt…

windows无界鼠标,多机共享一套键鼠

原因 当前使用一台笔记本和一个台式机。用起来很麻烦。想要找到共享键鼠的方案。找到了无界鼠标这个软件。 安装 在两台电脑上都安装powertoy应用。 https://github.com/microsoft/PowerToys csdn下载 安装完成后找到无界鼠标打开 配置 多台电脑配置相同的key,刷新识别设…

Unity3d调用C++ dll中的函数

一、生成dll 1.新建dll工程 2. 不用管dllmain.cpp&#xff0c;添加自定义Helper.h和Helper.cpp 3.添加要在外部调用的方法 //头文件 #define DLLEXPORT extern "C" __declspec(dllexport) DLLEXPORT int _stdcall Addition(int x, int y); DLLEXPORT int _stdcal…

LeetCode每日一题只 快乐数

目录 题目介绍&#xff1a; 算法原理&#xff1a; 鸽巢原理&#xff1a; 如何找到环里元素&#xff1a; 代码实现&#xff1a; 题目介绍&#xff1a; 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 算法原理&#xff1a; 我先简单举两个例子&#xff…

python界面开发 - OptionMenu菜单

文章目录 1. python图形界面开发1.1. Python图形界面开发——Tkinter1.2. Python图形界面开发——PyQt1.3. Python图形界面开发——wxPython1.4. Python图形界面开发—— PyGTK&#xff1a;基于GTK1.5. Python图形界面开发—— Kivy1.6. Python图形界面开发——可视化工具1.7. …

ABAQUS软件报价费用 abaqus正版购买价格多少钱?

ABAQUS软件可以完成哪些模拟&#xff1f; ABAQUS软件是一套功能强大的工程模拟的有限元软件&#xff0c;其解决问题的范围从相对简单的线性分析到许多复杂的非线性问题。ABAQUS软件中包含了一套丰富的单元库&#xff0c;可模拟任意几何形状&#xff1b;还包含了各种类型的材料…

【学习笔记】计算机视觉深度学习网络模型

这是本人学习计算机视觉CV领域深度学习模型的学习的一点点学习笔记&#xff0c;很多片子没有完成&#xff0c;可以作为学习的参考~

灵神笔记(1)----动态规划篇

文章目录 介绍动态规划入门&#xff1a;从记忆化搜索到递推打家劫舍递归记忆化递归递推滚动变量 背包0-1 背包递归写法记忆化递归 目标和记忆化搜索递推两个数组一个数组 完全背包记忆化递归搜索 零钱兑换记忆化递归递推 背包问题变形[至多|恰好|至少] 最长公共子序列记忆化搜索…

微信小程序开发系列(二十)·wxml语法·setData()修改对象类型数据、ES6 提供的展开运算符、delete和rest的用法

目录 1. 新增单个、多个属性 1.1 新增单个属性 1.2 新增多个属性 2. 修改单个、多个属性 2.1 修改单个属性 2.2 修改多个属性 3. 优化 3.1 ES6 提供的展开运算符 3.2 Object.assign()将多个对象合并为一个对象 4. 删除单个、多个属性 4.1 删除单个属性 …

搬运机器人助力制造业转型升级

随着传统制造业的转型升级&#xff0c;智能化和多样化成为行业发展的新趋势。在这个过程中&#xff0c;富唯智能搬运机器人作为智能工厂的重要搬运机器人&#xff0c;展现出了卓越的性能和适应性。 它不仅能够应对各种材料、形状和重量的搬运装卸需求&#xff0c;还能与智能物理…

跨链桥的类型总结/相关的名词解释

首先&#xff0c;这是一个会持续更新的文章&#xff0c;我会不断把自己了解到的跨链桥名词解释更新在这里。 跨链桥类型 基于传输方式分类&#xff1a; Lock and Mint&#xff1a;在一条链上锁定资产&#xff0c;在另一条链上铸造等价资产liqidity pool&#xff1a;在不同链…

数字化转型导师坚鹏:金融科技咨询方法论

金融科技咨询方法论 ——方法、做法、演法、心法 课程背景&#xff1a; 数字化转型背景下&#xff0c;很多机构存在以下问题&#xff1a; 不知道先进的金融科技咨询方法论&#xff1f; 不知道如何运作金融科技咨询项目&#xff1f; 不知道如何汇报咨询项目关键成果&…

第五十一回 李逵打死殷天赐 柴进失陷高唐州-AI发展历程和常用框架

朱仝说只要杀了李逵就上梁山&#xff0c;柴进就劝李逵先在庄上住一段时间&#xff0c;先让朱仝、雷横和吴用回了梁山。 李逵在柴进庄上住了一个月&#xff0c;碰到柴进的叔叔柴皇城病重来信叫他去一趟&#xff0c;于是李逵就随着柴进去了高唐州。 柴皇城被殷天锡气死&#xf…