Vuex中mutations和actions的那些事儿:为啥非要分家?

大家好,我是小杨,一个被Vuex虐过千百遍的前端老司机。今天咱们来聊聊Vuex里最让人困惑的两个概念------mutations和actions。为啥非要分开?为啥不能在mutations里写异步?看完这篇你就全明白了!

1. mutations:唯一能改state的"会计"

记得我刚用Vuex时,觉得mutations这玩意儿真多余,直接改state不香吗?后来项目出bug了才明白它的重要性。

mutations的核心特点

  • 唯一能修改state的地方(财务部独享修改权限)
  • 必须是同步函数(所有修改都要记录在案)
  • 通过commit触发(要走正规流程)
javascript 复制代码
// store/modules/user.js
const mutations = {
  // ✅ 正确的mutation
  SET_USER(state, user) {
    state.user = user
  },
  
  // ❌ 错误示范(虽然能运行,但违背设计原则)
  async SET_USER_ASYNC(state, user) {
    await someAsyncOperation()
    state.user = user // 千万别这么干!
  }
}

2. actions:处理异步的"业务员"

actions就像公司的业务部门,专门处理各种外部对接:

actions的核心特点

  • 可以包含异步操作(跟API打交道)
  • 不能直接修改state(没财务权限)
  • 通过dispatch触发(业务部门的工作流程)
javascript 复制代码
const actions = {
  async login({ commit }, credentials) {
    try {
      const user = await api.login(credentials) // 异步请求
      commit('SET_USER', user) // 走正规流程修改state
      return user
    } catch (error) {
      console.error('登录失败', error)
      throw error
    }
  }
}

3. 为啥非要分开?一次惨痛的教训

去年我做了一个电商项目,当时图省事在mutation里调接口:

javascript 复制代码
// ❌ 灾难性写法
mutations: {
  async GET_PRODUCTS(state) {
    state.loading = true
    const res = await api.getProducts() // 异步请求
    state.products = res.data
    state.loading = false
  }
}

结果出现两个致命问题:

  1. DevTools无法正确追踪状态变化
  2. 多个异步mutation导致状态更新顺序错乱

4. 官方为啥这么设计?

Vuex作者的设计意图其实很明确:

特性 mutations actions
能否修改state ✅ 能 ❌ 不能
同步/异步 ❌ 必须同步 ✅ 可以异步
触发方式 commit dispatch
定位 状态变更记录 业务逻辑处理

5. 我的最佳实践

经过多年踩坑,我总结出这样的分工原则:

javascript 复制代码
// 数据获取流程示例
actions: {
  async fetchData({ commit }) {
    commit('SET_LOADING', true) // mutation改状态
    const data = await api.getData() // action处理异步
    commit('SET_DATA', data) // mutation改状态
    commit('SET_LOADING', false)
    return data
  }
},

mutations: {
  SET_LOADING(state, isLoading) {
    state.isLoading = isLoading
  },
  SET_DATA(state, data) {
    state.data = data
  }
}

6. 特殊场景处理

有时候我们确实需要在mutation之后执行一些操作,可以用subscribe:

javascript 复制代码
// 在组件中监听mutation
this.$store.subscribe((mutation, state) => {
  if (mutation.type === 'SET_USER') {
    // 用户数据更新后的操作
    localStorage.setItem('user', JSON.stringify(state.user))
  }
})

7. 常见误区答疑

Q:我就是想在mutation里写异步,会怎样?

A:就像让会计去跑业务,短期可能没问题,但迟早会账目混乱!

Q:actions能直接改state吗?

A:技术上可以(通过this._vm),但千万别这么干,会破坏Vuex的可预测性

Q:小型项目也要这么严格吗?

A:养成分离的好习惯,项目大了才不会翻车

总结

记住这个黄金法则:

  • mutations:只管同步修改state(财务)
  • actions:处理异步和业务逻辑(业务)

就像公司要有明确的部门分工,Vuex也需要清晰的职责划分。现在你明白为啥Vuex要这么设计了吧?

⭐ 写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!

相关推荐
好家伙VCC1 天前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
未来之窗软件服务1 天前
未来之窗昭和仙君(六十五)Vue与跨地区多部门开发—东方仙盟练气
前端·javascript·vue.js·仙盟创梦ide·东方仙盟·昭和仙君
baidu_247438611 天前
Android ViewModel定时任务
android·开发语言·javascript
嘿起屁儿整1 天前
面试点(网络层面)
前端·网络
VT.馒头1 天前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
有位神秘人1 天前
Android中Notification的使用详解
android·java·javascript
phltxy1 天前
Vue 核心特性实战指南:指令、样式绑定、计算属性与侦听器
前端·javascript·vue.js
Byron07071 天前
Vue 中使用 Tiptap 富文本编辑器的完整指南
前端·javascript·vue.js
css趣多多1 天前
地图快速上手
前端
zhengfei6111 天前
面向攻击性安全专业人员的一体化浏览器扩展程序[特殊字符]
前端·chrome·safari