Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式和库,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,Vuex 解决了多个组件共享状态时的通信问题,特别是在大型应用中,组件层级嵌套较深时,通过 props 和 events 进行数据传递会变得非常复杂,下面将详细介绍 Vuex 的使用方法,包括核心概念、安装配置、模块化以及实际应用场景。

Vuex 的核心概念
Vuex 的核心概念包括 State、Getters、Mutations、Actions 和 Modules,理解这些概念是掌握 Vuex 的关键。
-
State
State 是 Vuex 存储的单一数据源,所有组件的状态都存储在 State 中,组件可以通过this.$store.state
或使用mapState
辅助函数来获取状态,如果 State 中有一个count
属性,组件中可以通过this.$store.state.count
访问它,为了避免在组件中频繁书写this.$store.state
,可以使用mapState
将 State 中的属性映射到组件的计算属性中,使代码更简洁。 -
Getters
Getters 类似于 Vue 中的计算属性,用于对 State 中的数据进行加工处理,如果 State 中有一个todos
数组,Getters 可以定义一个completedTodos
来筛选出已完成的任务,组件可以通过this.$store.getters.completedTodos
或mapGetters
辅助函数访问 Getters,Getters 可以接收 State 作为参数,也可以接收其他 Getters 作为参数,支持链式调用。 -
Mutations
Mutations 是唯一可以修改 State 的方式,它是一个包含 type 和 callback 的对象,callback 接收 State 作为参数,在组件中通过this.$store.commit('mutationName', payload)
来触发 Mutations,需要注意的是,Mutations 必须是同步函数,因为异步操作会导致 State 的变化无法被追踪,一个增加 count 的 Mutation 可以定义为INCREMENT(state, payload) { state.count += payload; }
,组件通过commit('INCREMENT', 10)
来调用。(图片来源网络,侵删) -
Actions
Actions 用于处理异步操作,API 请求、定时器等,Actions 通过this.$store.dispatch('actionName', payload)
触发,内部可以包含多个 Mutations 调用,Actions 接收一个 context 对象,包含commit
、dispatch
、state
等方法,一个异步获取用户数据的 Action 可以先发起 API 请求,成功后调用commit('SET_USER', data)
来更新 State,Actions 可以被其他 Actions 调用,也支持链式调用。 -
Modules
当应用变得复杂时,可以将 Store 拆分为多个 Modules,每个 Module 拥有自己的 State、Getters、Mutations 和 Actions,Modules 可以通过namespaced: true
启用命名空间,避免命名冲突,一个用户模块和一个购物车模块,分别管理用户信息和购物车数据,通过namespaced: true
后,访问 Module 中的 State 需要加上模块名,如this.$store.state.user.userInfo
。
Vuex 的安装与配置
在使用 Vuex 之前,需要先安装 Vuex,可以通过 npm 或 yarn 安装:
npm install vuex --save
或 yarn add vuex
安装完成后,在 Vue 项目的入口文件 main.js
中引入并配置 Vuex。

import Vue from 'vue'; import Vuex from 'vuex'; import appStore from './store'; // 引入自定义的 Store 文件 Vue.use(Vuex); const store = new Vuex.Store({ state: { count: 0, todos: [] }, mutations: { INCREMENT(state, payload) { state.count += payload; } }, actions: { incrementAsync({ commit }, payload) { setTimeout(() => { commit('INCREMENT', payload); }, 1000); } }, getters: { completedTodos: state => state.todos.filter(todo => todo.completed) } }); new Vue({ store, render: h => h(App) }).$mount('#app');
在实际开发中,通常会将 Store 单独拆分为一个文件,store/index.js
,便于维护和管理。
Vuex 的模块化实践
当应用规模较大时,使用模块化可以有效拆分 Store,一个电商应用可以分为用户模块、商品模块和购物车模块:
// store/modules/user.js const userModule = { namespaced: true, state: { userInfo: null }, mutations: { SET_USER(state, payload) { state.userInfo = payload; } }, actions: { fetchUser({ commit }) { // 模拟 API 请求 const userData = { name: 'John', age: 30 }; commit('SET_USER', userData); } } }; // store/modules/cart.js const cartModule = { namespaced: true, state: { items: [] }, mutations: { ADD_TO_CART(state, payload) { state.items.push(payload); } } }; // store/index.js import Vue from 'vue'; import Vuex from 'vuex'; import userModule from './modules/user'; import cartModule from './modules/cart'; Vue.use(Vuex); export default new Vuex.Store({ modules: { user: userModule, cart: cartModule } });
在组件中访问模块化的 State 和方法时,需要指定模块名:
this.$store.state.user.userInfo
或 this.$store.dispatch('user/fetchUser')
,使用 mapState
和 mapActions
时,可以通过对象语法指定模块名,mapState('user', ['userInfo'])
。
Vuex 的实际应用场景
Vuex 适用于以下场景:
- 多组件共享状态:用户登录信息需要在多个组件中显示,使用 Vuex 可以避免通过 props 逐层传递。
- 复杂的状态逻辑:购物车中的商品数量计算、价格统计等,可以通过 Getters 和 Mutations 统一管理。
- 异步操作与状态更新:从后端获取数据后更新 State,通过 Actions 处理异步请求,通过 Mutations 更新 State。
Vuex 的注意事项
- 避免滥用 Vuex:对于简单的组件间通信,使用 props 和 events 即可,无需引入 Vuex。
- Mutations 必须同步:异步操作应放在 Actions 中,确保 State 的变化可预测。
- 合理使用模块化:避免模块划分过细或过粗,保持代码的可维护性。
相关问答 FAQs
问题 1:Vuex 和 Pinia 有什么区别?
答:Pinia 是 Vue 3 官方推荐的状态管理库,相比 Vuex,Pinia 更简洁、类型支持更好,且不需要嵌套模块(支持扁平化结构),Pinia 支持多个 Store,且没有 Mutations 和 Actions 的严格区分,可以直接修改 State(但推荐使用 Actions),对于 Vue 3 项目,Pinia 是更现代的选择;Vue 2 项目仍可以使用 Vuex。
问题 2:如何在组件中使用 mapState 和 mapActions?
答:mapState
和 mapActions
是 Vuex 提供的辅助函数,用于简化组件中的 State 和 Actions 访问。
import { mapState, mapActions } from 'vuex'; export default { computed: { ...mapState(['count', 'todos']), // 将 State 映射到计算属性 ...mapState('user', ['userInfo']) // 映射模块化的 State }, methods: { ...mapActions(['incrementAsync']), // 将 Actions 映射到方法 ...mapActions('cart', ['addToCart']) // 映射模块化的 Actions } };
通过这些辅助函数,可以避免在组件中直接使用 this.$store
,使代码更清晰。