深入理解 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.rhkb.cn/news/270544.html

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

相关文章

C++——string类

前言&#xff1a;哈喽小伙伴们&#xff0c;从这篇文章开始我们将进行若干个C中的重要的类容器的学习。本篇文章将讲解第一个类容器——string。 目录 一.什么是string类 二.string类常见接口 1.string类对象的常见构造 2.string类对象的容量操作 3. string类对象的访问及遍…

代码随想录第51天|● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

文章目录 ● 300.最长递增子序列思路代码&#xff1a; ● 674. 最长连续递增序列思路&#xff1a;代码&#xff1a; ● 718. 最长重复子数组思路&#xff1a;代码一&#xff1a;dp二维数组代码二&#xff1a;滚动数组 ● 300.最长递增子序列 思路 dp[i]表示i之前包括i的以nums…

从 Language Model 到 Chat Application:对话接口的设计与实现

作者&#xff1a;网隐 RTP-LLM 是阿里巴巴大模型预测团队开发的大模型推理加速引擎&#xff0c;作为一个高性能的大模型推理解决方案&#xff0c;它已被广泛应用于阿里内部。本文从对话接口的设计出发&#xff0c;介绍了业界常见方案&#xff0c;并分享了 RTP-LLM 团队在此场景…

MySQL下实现纯SQL语句的递归查询

需求 有一个部门表&#xff0c;部门表中有一个字段用于定义它的父部门&#xff1b; 在实际业务中有一个『部门中心』的业务&#xff1b; 比如采购单&#xff0c;我们需要显示本部门及子部门的采购单显示出来。 结构 数据如下&#xff1a; 实现方式如下&#xff1a; WITH RECUR…

Vue点击切换组件颜色

例如我有一个这样的组件&#xff0c;我希望在点击组件之后由蓝色变成橙色 先把原来的代码附上(简化掉了叉号&#xff09;&#xff1a; <div v-for"(item, index) in words" :key"index" class"scrollbar-demo-item"><span>{{ item …

Unreal 5打开Windows虚拟键盘的权限问题

可以通过以下代码打开Windows虚拟键盘 void UMouseSimulatorBPLibrary::ShowVirtualKeyboard() {TCHAR* OskPath L"C:\\Program Files\\Common Files\\microsoft shared\\ink\\TabTip.exe";if (!FPaths::FileExists(OskPath)){OskPath L"C:\\windows\\system…

比较 2 名无人机驾驶员:借助分析飞得更高

近年来&#xff0c;越来越多的政府和执法机构使用无人机从空中鸟瞰。为了高效执行任务&#xff0c;无人机必须能够快速机动到预定目标。快速机动使它们能够在复杂的环境中航行&#xff0c;并高效地完成任务。成为认证的无人机驾驶员的要求因国家/地区而异&#xff0c;但都要求您…

数字人民币钱包(二)

文章目录 前言一 什么是数字人民币钱包&#xff1f;二 怎么开通数字人民币钱包&#xff1f;三 数字人民币钱包有哪些&#xff1f;四 数字人民币钱包升级 前言 上篇文章梳理了什么是数字人民币&#xff0c;及其特征和相关概念&#xff0c;这篇文章来整理下数字人民币钱包。数字人…

Redis线程模型解析

引言 Redis是一个高性能的键值对&#xff08;key-value&#xff09;内存数据库&#xff0c;以其卓越的读写速度和灵活的数据类型而广受欢迎。在Redis 6.0之前的版本中&#xff0c;它采用的是一种独特的单线程模型来处理客户端的请求。尽管单线程在概念上似乎限制了其扩展性和并…

【笔记】Android ServiceStateTracker 网络状态变化逻辑及SPN更新影响

业务简介 在网络状态变化的时候&#xff08;数据或WiFi&#xff09;&#xff0c;会更新SPN。 基于Android U的代码分析。 分类&#xff1a;SPN Data_Dic-的博客-CSDN博客 功能逻辑 状态说明 飞行模式下注册上WFC的话&#xff0c;注册状态MD上报 regState: NOT_REG_MT_NOT…

【注意】宽泛负载!

放大器输出摆幅会限制可测量的负载电流范围。例如&#xff0c;从 100mV 至 4.9V 的输出摆幅相当于频程约 15 倍的线性输出范围。那么如果要测量 30 倍频程的负载电流&#xff0c;应该怎么做&#xff1f;调节增益&#xff01; 在TIE2E 论坛上为客户提供支持时&#xff0c;我遇到…

CUDA学习笔记05:卷积(sobel)

参考资料 CUDA编程模型系列四(卷积 or sobel边缘检测)_哔哩哔哩_bilibili 强推 ! ! 代码片段 主函数: #include <stdio.h> #include <iostream> #include <math.h> #include <opencv2/opencv.hpp> #include <opencv2/core.hpp> #include &l…

Java设计模式:建造者模式之经典与流式的三种实现(四)

本文将深入探讨Java中建造者模式的两种实现方式&#xff1a;经典建造者与流式建造者。建造者模式是一种创建型设计模式&#xff0c;它允许你构建复杂对象的步骤分解&#xff0c;使得对象的创建过程更加清晰和灵活。我们将通过示例代码详细解释这两种实现方式&#xff0c;并分析…

十:套接字和标准I/O,以及分离I/O流

1 标准I/O函数的优点 C语言标准IO整理 1.1 标准I/O函数的两个优点 标准I/O函数具有良好的移植性。 标准I/O函数可以利用缓冲提高性能 从图中可以看出&#xff0c;使用标准I/O函数传输数据时&#xff0c;经过两个缓冲。例如&#xff0c;使用fputs函数传输字符串 “Hello” 时…

安卓游戏开发之图形渲染技术优劣分析

一、引言 随着移动设备的普及和性能的提升&#xff0c;安卓游戏开发已经成为一个热门领域。在安卓游戏开发中&#xff0c;图形渲染技术是关键的一环。本文将对安卓游戏开发中常用的图形渲染技术进行分析&#xff0c;比较它们的优劣&#xff0c;并探讨它们在不同应用场景下的适用…

关于 selinux 规则

1. 查看selinux状态 SELinux的状态&#xff1a; enforcing&#xff1a;强制&#xff0c;每个受限的进程都必然受限 permissive&#xff1a;允许&#xff0c;每个受限的进程违规操作不会被禁止&#xff0c;但会被记录于审计日志 disabled&#xff1a;禁用 相关命令&#xf…

manjaro 安装 wps 教程

内核: Linux 6.6.16.2 wps-office版本&#xff1a; 11.10.11719-1 本文仅作为参考使用, 如果以上版本差别较大不建议参考 安装wps主体 yay -S wps-office 安装wps字体 &#xff08;如果下载未成功看下面的方法&#xff09; yay -S ttf-waps-fonts 安装wps中文语言 yay …

upload-Labs靶场“11-15”关通关教程

君衍. 一、第十一关 %00截断GET上传1、源码分析2、%00截断GET上传 二、第十二关 %00截断POST上传1、源码分析2、%00截断POST上传 三、第十三关 文件头检测绕过1、源码分析2、文件头检测绕过 四、第十四关 图片检测绕过上传1、源码分析2、图片马绕过上传 五、第十五关 图片检测绕…

mysql学习笔记8——常用5个内置方法

1count 对查询内容进行计数&#xff0c;并返回结果 2as as可以将查询出来结果赋予新名字 3sum sum可以查询某字段特定条件下的和值 4concat concat可以将多列数据合并成一列&#xff0c;只要concat&#xff08;&#xff09;即可 5group_concat group_concat可以把多列…

Docker的镜像操作

目录 镜像的操作(**开头为常用请留意) 镜像查找 **拉取镜像 **推送镜像 **查看镜像 **修改镜像名称 **查看镜像的详细信息 ​编辑 删除镜像 查看所有镜像ID 删除全部镜像 **查看镜像的操作历史 镜像迁移 镜像打包 远程发送镜像(需要先打包) 本地镜像tar包恢复 镜像过…