当前位置:   article > 正文

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

深入理解 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() // 引用类型变量
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

②在 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
  }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在这个示例中,我们定义了两个模块 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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

特点:

  • 直接访问 $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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

特点:

  • 使用 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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

④模块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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
⑤用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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在这个案例中,我们展示了五种使用 的 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);
    }
  }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在 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 来获取所有已完成的任务
    }
  }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
③模块间的 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'];
    }
  }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

从这个角度看,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;
    }
  }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 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 }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
③应用场景
  • 修改单个状态:当需要修改 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!'
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

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);
    }
  }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在 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');
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
③特点
  • 异步操作: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
    })
  }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2.mapGetters:

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

import { mapGetters } from 'vuex';

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

    ...mapGetters({
      formattedMessage: 'formattedMessage'
    })
  }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3.mapMutations:

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

import { mapMutations } from 'vuex';

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

    ...mapMutations({
      setUserName: 'SET_USER_NAME'
    })
  }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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

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

{
  increment: function() {
    return this.$store.commit('increment');
  },
  decrement: function() {
    return this.$store.commit('decrement');
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

它将 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'
    })
  }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

通常情况下,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);
    }
  }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

在上面的示例中,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,我们可以有效地管理复杂的状态逻辑,并且提高项目的开发效率和质量。

文章参考

项目地址


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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/231832
推荐阅读
相关标签