news 2026/4/15 23:42:28

Vue进阶实战06,吃透 Vuex 核心概念:State/Mutation/Action/Getter 拆解与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue进阶实战06,吃透 Vuex 核心概念:State/Mutation/Action/Getter 拆解与实战

在 Vue 项目开发中,当组件间需要共享状态、跨层级通信时,单纯依靠propsemit会让代码变得杂乱且难以维护。Vuex 作为 Vue 官方的状态管理库,通过集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

本文将从 Vuex 的四大核心概念(State、Mutation、Action、Getter)入手,层层拆解其设计理念、使用方式和最佳实践,帮你彻底搞懂 Vuex 的核心逻辑。

一、Vuex 核心架构:先理清整体逻辑

在拆解具体概念前,先明确 Vuex 的核心设计原则:单向数据流。Vuex 的状态流转遵循:View(视图)→ Action(动作)→ Mutation(变更)→ State(状态)→ View(视图)

  • View 触发 Action(可包含异步操作);
  • Action 提交 Mutation(不能异步);
  • Mutation 修改 State;
  • State 更新后驱动 View 重新渲染。

这种设计让状态变更轨迹清晰可追溯,避免了直接修改状态导致的不可预测问题。

二、State:唯一的状态数据源

1. 核心作用

State 是 Vuex 的 “数据仓库”,存储应用的所有共享状态,且唯一(一个 Vuex 实例只能有一个 State)。它相当于组件中的data,但作用域是全局的,所有组件都能访问。

2. 基本使用

(1)定义 State
// store/index.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ // 定义共享状态 state: { count: 0, userInfo: { name: '张三', age: 25 }, todos: [ { id: 1, text: '学习Vuex', done: true }, { id: 2, text: '拆解核心概念', done: false } ] } })
(2)组件中访问 State

有两种常用方式:

  • 方式 1:直接通过$store访问
<template> <div> <p>当前计数:{{ $store.state.count }}</p> <p>用户名:{{ $store.state.userInfo.name }}</p> </div> </template>
  • 方式 2:通过mapState辅助函数映射(推荐,简化代码)适用于需要访问多个 State 的场景,将 State 映射为组件的计算属性:
<template> <div> <p>当前计数:{{ count }}</p> <p>用户名:{{ userName }}</p> <p>待办列表:{{ todos }}</p> </div> </template> <script> import { mapState } from 'vuex' export default { computed: { // 方式1:数组形式(映射的计算属性名与State属性名一致) ...mapState(['count', 'todos']), // 方式2:对象形式(自定义计算属性名) ...mapState({ userName: state => state.userInfo.name, // 简化写法(当函数体仅返回state属性时) userAge: 'userInfo.age' }) } } </script>

3. 注意事项

  • State 是响应式的:修改 State 后,依赖该状态的组件会自动更新;
  • 不要直接修改 State:必须通过 Mutation(这是 Vuex 的核心规则,保证状态变更可追踪)。

三、Mutation:唯一能修改 State 的 “钥匙”

1. 核心作用

Mutation 是修改 Vuex 中 State 的唯一方式,所有对 State 的同步修改都必须通过 Mutation 完成。每个 Mutation 都有一个字符串类型的type和一个handler(实际修改状态的函数)。

2. 基本使用

(1)定义 Mutation
// store/index.js export default new Vuex.Store({ state: { count: 0 }, mutations: { // 定义修改count的mutation increment(state) { state.count++ }, // 带参数的mutation(参数称为payload) incrementByNum(state, num) { state.count += num }, // payload为对象的情况(推荐,可传递多个参数) incrementWithObj(state, payload) { state.count += payload.num state.userInfo.age += payload.age } } })
(2)提交 Mutation

组件中通过commit提交 Mutation,不能直接调用 mutation 函数:

<template> <div> <p>当前计数:{{ count }}</p> <button @click="add">加1</button> <button @click="addByNum">加5</button> <button @click="addWithObj">加3且年龄加1</button> </div> </template> <script> import { mapState } from 'vuex' export default { computed: { ...mapState(['count']) }, methods: { add() { // 方式1:直接提交type this.$store.commit('increment') }, addByNum() { // 方式2:提交带payload的mutation this.$store.commit('incrementByNum', 5) }, addWithObj() { // 方式3:以对象形式提交(更清晰) this.$store.commit({ type: 'incrementWithObj', num: 3, age: 1 }) } } } </script>
(3)mapMutations辅助函数

简化 mutation 提交,将 mutation 映射为组件的 methods:

<script> import { mapState, mapMutations } from 'vuex' export default { computed: { ...mapState(['count']) }, methods: { // 映射mutation为方法 ...mapMutations(['increment', 'incrementByNum']), // 自定义方法名 ...mapMutations({ add: 'increment', addNum: 'incrementByNum' }), addWithObj() { this.$store.commit({ type: 'incrementWithObj', num: 3, age: 1 }) } } } </script>

3. 核心规则

  • 必须是同步函数:如果在 mutation 中写异步代码(如 setTimeout),Vuex 无法追踪状态变更的准确时机,调试工具也无法正确记录状态变化;
  • 仅负责修改状态:不要在 mutation 中做业务逻辑(如请求数据、判断逻辑),业务逻辑应放在 Action 中。

四、Action:处理异步的 “中间件”

1. 核心作用

Action 用于处理异步操作和复杂业务逻辑,最终通过提交 Mutation 来修改 State(不能直接修改 State)。Action 支持异步操作(如 AJAX 请求、定时器),这是它与 Mutation 的核心区别。

2. 基本使用

(1)定义 Action
// store/index.js export default new Vuex.Store({ state: { count: 0, userList: [] }, mutations: { increment(state) { state.count++ }, setUserList(state, list) { state.userList = list } }, actions: { // 简单异步action(带context参数,包含store的所有方法/属性) incrementAsync(context) { setTimeout(() => { // 提交mutation修改状态 context.commit('increment') }, 1000) }, // 解构context简化代码(常用) incrementAsyncWithNum({ commit }, num) { setTimeout(() => { commit('incrementByNum', num) }, 1000) }, // 异步请求数据的action async fetchUserList({ commit }) { try { const res = await fetch('/api/userList') const data = await res.json() commit('setUserList', data) } catch (err) { console.error('请求失败:', err) } } } })
(2)分发 Action

组件中通过dispatch分发 Action:

<template> <div> <p>当前计数:{{ count }}</p> <button @click="addAsync">1秒后加1</button> <button @click="addAsyncByNum">1秒后加5</button> <button @click="getUserList">获取用户列表</button> </div> </template> <script> import { mapState } from 'vuex' export default { computed: { ...mapState(['count', 'userList']) }, methods: { addAsync() { this.$store.dispatch('incrementAsync') }, addAsyncByNum() { // 分发带payload的action this.$store.dispatch('incrementAsyncWithNum', 5) }, getUserList() { this.$store.dispatch('fetchUserList') } } } </script>
(3)mapActions辅助函数

将 Action 映射为组件的 methods,简化分发操作:

<script> import { mapState, mapActions } from 'vuex' export default { computed: { ...mapState(['count', 'userList']) }, methods: { ...mapActions(['incrementAsync', 'fetchUserList']), // 自定义方法名 ...mapActions({ addAsyncNum: 'incrementAsyncWithNum' }), handleAdd() { this.addAsyncNum(5) } } } </script>

3. 核心特性

  • 支持异步:可在 Action 中执行任意异步操作(请求、定时器等);
  • 可组合:Action 之间可以互相调用,处理复杂业务逻辑:
actions: { actionA({ dispatch }) { return new Promise(resolve => { setTimeout(() => { dispatch('actionB') resolve() }, 1000) }) }, actionB({ commit }) { commit('increment') } }

五、Getter:对 State 的 “计算属性”

1. 核心作用

Getter 相当于 Vuex 的 “计算属性”,用于对 State 中的数据进行加工处理(如过滤、排序、拼接),返回新的结果。Getter 的返回值会根据其依赖的 State 自动缓存,只有当依赖的 State 变化时才会重新计算。

2. 基本使用

(1)定义 Getter
// store/index.js export default new Vuex.Store({ state: { todos: [ { id: 1, text: '学习Vuex', done: true }, { id: 2, text: '拆解核心概念', done: false }, { id: 3, text: '实战练习', done: false } ], count: 0 }, getters: { // 基础用法:获取已完成的待办 doneTodos: state => { return state.todos.filter(todo => todo.done) }, // 获取已完成待办的数量(依赖其他getter) doneTodosCount: (state, getters) => { return getters.doneTodos.length }, // 带参数的getter(返回函数,实现传参) getTodoById: state => id => { return state.todos.find(todo => todo.id === id) }, // 组合计算 doubleCount: state => { return state.count * 2 } } })
(2)访问 Getter
  • 方式 1:通过$store.getters访问
<template> <div> <p>已完成待办:{{ $store.getters.doneTodos.length }} 条</p> <p>ID为1的待办:{{ $store.getters.getTodoById(1).text }}</p> <p>计数翻倍:{{ $store.getters.doubleCount }}</p> </div> </template>
  • 方式 2:mapGetters辅助函数将 Getter 映射为组件的计算属性:
<template> <div> <p>已完成待办:{{ doneTodosCount }} 条</p> <p>计数翻倍:{{ doubleCount }}</p> </div> </template> <script> import { mapGetters } from 'vuex' export default { computed: { // 数组形式映射 ...mapGetters(['doneTodosCount', 'doubleCount']), // 自定义名称映射 ...mapGetters({ doneCount: 'doneTodosCount', double: 'doubleCount' }), // 结合本地计算属性 todoText() { return this.$store.getters.getTodoById(2).text } } } </script>

3. 核心优势

  • 缓存性:依赖不变时,多次访问 Getter 不会重复计算;
  • 复用性:将通用的状态处理逻辑抽离到 Getter,避免组件中重复写相同代码;
  • 纯函数:Getter 仅依赖 State 和其他 Getter,不产生副作用,保证结果可预测。

六、核心概念对比与总结

概念核心作用是否可异步是否能直接修改 State调用方式
State存储共享状态--组件中通过$store.state访问
Mutation同步修改 State是(唯一方式)$store.commit('type')
Action处理异步 / 业务逻辑,提交 Mutation$store.dispatch('type')
Getter加工 State 数据(计算属性)-$store.getters.xxx

最佳实践

  1. 遵循单向数据流:View → Action → Mutation → State → View;
  2. 简单同步修改:直接提交 Mutation;
  3. 异步 / 复杂逻辑:先写 Action,再在 Action 中提交 Mutation;
  4. 状态加工:使用 Getter 抽离通用逻辑,避免组件重复代码;
  5. 辅助函数:mapState/mapMutations/mapActions/mapGetters简化代码,提升可读性;
  6. 模块化:当项目复杂时,使用 Vuex 的 Module 拆分状态(后续可单独拆解)。

七、最后

Vuex 的四大核心概念围绕 “可预测的状态管理” 设计,理解它们的分工和协作逻辑,就能轻松应对组件间的状态共享问题。记住:State 存数据,Mutation 改数据(同步),Action 处理异步 / 业务,Getter 加工数据

从简单场景入手,逐步尝试异步 Action、Getter 缓存、辅助函数等特性,你会发现 Vuex 能让复杂应用的状态管理变得清晰、可控。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 6:04:35

FileConverter:Windows右键菜单的终极文件转换方案

FileConverter&#xff1a;Windows右键菜单的终极文件转换方案 【免费下载链接】FileConverter File Converter is a very simple tool which allows you to convert and compress one or several file(s) using the context menu in windows explorer. 项目地址: https://gi…

作者头像 李华
网站建设 2026/4/15 18:17:16

5个HTML转PDF常见痛点,html-to-pdfmake如何轻松解决?

你是不是也遇到过这样的困扰&#xff1a;精心设计的HTML页面在转换为PDF时样式全乱套了&#xff1f;表格跨行跨列完全错位&#xff1f;图片要么不显示要么分辨率惨不忍睹&#xff1f;别担心&#xff0c;html-to-pdfmake这个神器正是为你量身打造的解决方案&#xff01; 【免费下…

作者头像 李华
网站建设 2026/4/16 13:02:07

RS ASIO完整教程:3分钟解决摇滚史密斯音频延迟困扰

RS ASIO完整教程&#xff1a;3分钟解决摇滚史密斯音频延迟困扰 【免费下载链接】rs_asio ASIO for Rocksmith 2014 项目地址: https://gitcode.com/gh_mirrors/rs/rs_asio 还在为《摇滚史密斯2014重制版》中吉他的声音总是慢半拍而烦恼&#xff1f;专业音频接口配合RS A…

作者头像 李华
网站建设 2026/4/16 14:32:16

Ludusavi:专业级游戏存档备份工具完整指南

Ludusavi&#xff1a;专业级游戏存档备份工具完整指南 【免费下载链接】ludusavi Backup tool for PC game saves 项目地址: https://gitcode.com/gh_mirrors/lu/ludusavi 对于PC游戏玩家来说&#xff0c;最令人痛心的莫过于因系统重装、游戏崩溃或意外删除而丢失数十小…

作者头像 李华
网站建设 2026/4/16 10:10:02

如何快速提取TikTok视频字幕:一键获取文案的完整指南

如何快速提取TikTok视频字幕&#xff1a;一键获取文案的完整指南 【免费下载链接】TikTokDownload 抖音去水印批量下载用户主页作品、喜欢、收藏、图文、音频 项目地址: https://gitcode.com/gh_mirrors/ti/TikTokDownload 在短视频内容创作日益火热的今天&#xff0c;快…

作者头像 李华
网站建设 2026/4/16 12:58:48

Bodymovin插件魔法:从AE动画到网页动效的华丽变身记

Bodymovin插件魔法&#xff1a;从AE动画到网页动效的华丽变身记 【免费下载链接】bodymovin-extension Bodymovin UI extension panel 项目地址: https://gitcode.com/gh_mirrors/bod/bodymovin-extension &#x1f3ac; 想象一下&#xff1a;你在After Effects中精心制…

作者头像 李华