Vuex的左右护法:actions和mutations到底有啥不同?

0 阅读3分钟

大家好,我是小杨,一个在Vuex世界里摸爬滚打6年的前端码农。今天咱们来聊聊Vuex里最让人头秃的两个概念——actions和mutations。这俩货长得像双胞胎,用起来却天差地别,不知道坑过多少新手(包括当年的我😅)。

1. 先看个真实场景:用户登录流程

上周我review代码时看到这样的写法:

// ❌ 新手常见错误写法
mutations: {
  async login(state, credentials) {
    const user = await api.login(credentials)
    state.user = user
  }
}

看起来没啥问题对吧?但这是个典型的反模式!让我告诉你为什么不能这么写。

2. mutations:只能干同步活的"老实人"

mutations在Vuex里的定位非常明确:

  • 唯一能修改state的地方(其他途径修改会被Vuex警告)
  • 必须是同步操作(就像会计记账必须实时)
  • 通过commit触发(要走正规流程)
// ✅ 正确的mutation写法
mutations: {
  SET_USER(state, user) {
    state.user = user // 同步修改
  }
}

3. actions:能处理异步的"灵活派"

actions则是完全不同的存在:

  • 可以包含异步操作(适合API调用)
  • 不能直接修改state(必须通过commit)
  • 通过dispatch触发(业务逻辑入口)
// ✅ 正确的action写法
actions: {
  async login({ commit }, credentials) {
    const user = await api.login(credentials) // 异步操作
    commit('SET_USER', user) // 通过mutation修改state
    return user
  }
}

4. 为什么非要分开?血泪教训

去年我参与的一个项目,有人把异步逻辑全写在mutations里,结果:

  1. DevTools的时间旅行调试直接废了
  2. 多个异步mutation导致状态竞争问题
  3. 代码像意大利面条一样难维护

5. 一张表看懂区别

特性mutationsactions
修改state✅ 唯一权限❌ 必须通过commit
异步操作❌ 严禁异步✅ 可以任意异步
触发方式commitdispatch
适合场景纯状态变更业务逻辑+异步操作
DevTools支持✅ 完整追踪✅ 但只记录dispatch

6. 最佳实践:各司其职

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

// 数据获取标准流程
actions: {
  async fetchData({ commit }) {
    commit('SET_LOADING', true) // mutation改状态
    try {
      const data = await api.getData() // 异步请求
      commit('SET_DATA', data) // mutation改状态
      return data
    } finally {
      commit('SET_LOADING', false)
    }
  }
}

7. 常见问题解答

Q:我就是想在mutation里调用API怎么办?
A:除非你想被同事追杀,否则千万别!把API调用放到action里。

Q:action里能直接改state吗?
A:技术上可以(通过store._vm),但这是破坏约定的危险操作!

Q:小型项目也要这么严格吗?
A:好习惯要从小培养,等项目大了再改就晚了。

8. 特殊技巧:action返回Promise

我特别喜欢这样写:

// 组件中调用
methods: {
  async handleLogin() {
    try {
      await this.$store.dispatch('login', credentials)
      // 登录成功后的操作
    } catch (error) {
      // 错误处理
    }
  }
}

总结

记住这个黄金法则:

  • mutations:只管同步修改state(简单直接)
  • actions:处理业务逻辑和异步(灵活多变)

就像公司里财务和业务部门要分工明确,Vuex中的这两个概念也必须各司其职。现在你该明白为啥Vuex要这么设计了吧?

⭐  写在最后

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

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

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

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

✅ 解答我文章中一些疑问

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

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

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

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