Code前端首页关于Code前端联系我们

不少刚学Vuex的同学都会疑惑,mutations和actions看起来都能搞事情,但到底哪里不一样?今天就把这俩的区别掰碎了讲,从职责、用法到实际开发场景,一次性讲清楚~

terry 2天前 阅读数 29 #Vue

修改状态的“规则” vs 业务逻辑的“载体”

Vuex的设计里,state是存储数据的“仓库”,而mutationsactions是控制数据变化的“开关”,但分工完全不同:

  • mutations:状态修改的“唯一合法通道”
    它是Vuex里唯一允许直接修改state的地方,有点像银行柜台——只有它能合法“动”账户里的钱,比如state里存了个count,想让count加1,就得在mutations里写个increment函数,专门负责改这个值,而且mutation必须是同步操作,因为要让Vuex的调试工具(devtools)能精准追踪每一次状态变化,调试时能回退、能看变化记录。

  • actions:业务逻辑的“协调者”
    它不直接碰state,而是触发mutation来间接改状态,actions主打处理异步操作(比如调接口、用定时器),还能整合多个mutation或其他action,相当于“业务流程管家”,举个例子:用户登录时,action要先调后端接口拿token(这是异步),拿到后再通过commit mutation把token存到state里,这里action负责“登录流程”这个完整业务,mutation只负责单纯的状态修改。

使用场景:什么时候用mutation,什么时候用action?

用生活场景类比更直观:

  • 该用mutation的场景:纯状态修改,没异步、没复杂逻辑。
    点击按钮让数字加1”“切换主题颜色”“修改用户昵称”——这些操作“直给”,不需要等、不需要和外部交互,直接改状态就行,代码里就是定义一个mutation类型(比如SET_NICKNAME),接收新昵称当参数,然后commit这个mutation。

  • 该用action的场景:有异步、有多步骤、要和外部交互(比如调API、操作本地存储)。
    加载用户信息”:action里得先调接口getUserInfo(),拿到数据后,再commit多个mutation(比如SET_USERNAME改用户名、SET_AVATAR改头像);再比如“购物车结算”:action里要检查库存(调接口)、生成订单(调接口)、修改购物车状态(commit mutation),这些步骤得串起来,action就负责统筹。

简单总结:只要涉及“等一下再改状态”(异步)或者“改状态前要做很多事”(复杂逻辑),就用action;单纯“现在改状态”,用mutation。

语法与调用方式:直接触发 vs 异步触发

从代码怎么写、怎么调,也能看出两者区别:

  • mutation的写法与调用
    在store的mutations里定义函数,第一个参数是state(要改的状态对象),第二个是payload(传递的数据),触发时用this.$store.commit('mutation名称', 数据)

    mutations: {
      SET_COUNT(state, newCount) {
        state.count = newCount; // 直接改state
      }
    }
    // 组件里触发:
    this.$store.commit('SET_COUNT', 10);

    注意!mutation里绝对不能写异步代码(比如setTimeoutaxios请求),否则devtools追踪不到状态变化,调试时会乱套。

  • action的写法与调用
    在store的actions里定义函数,第一个参数是context(包含commitdispatchstate等方法),也可以解构用{ commit },触发时用this.$store.dispatch('action名称', 数据),而且action里能自由写异步,

    actions: {
      async fetchUserInfo({ commit }) {
        const res = await axios.get('/user'); // 异步请求
        commit('SET_USER', res.data); // 用mutation改状态
      }
    }
    // 组件里触发:
    this.$store.dispatch('fetchUserInfo');

    action还能返回Promise,方便外部用.then()await处理,比如登录成功后跳转页面:

    actions: {
      login({ commit }, userInfo) {
        return axios.post('/login', userInfo)
          .then(res => {
            commit('SET_TOKEN', res.data.token);
            return res.data; // 把数据返回给调用处
          });
      }
    }
    // 组件里用:
    this.$store.dispatch('login', { username, password })
      .then(() => {
        this.$router.push('/home'); // 登录成功跳转
      });

严格模式下的约束差异

Vuex有个严格模式(配置strict: true),打开后对状态修改的约束更严格,这时候mutation和action的区别会被放大:

  • mutation在严格模式下:只有通过它修改state才合法,如果在组件里直接写this.$store.state.count = 10,控制台会报错,这强制要求“状态修改必须走mutation”,保证每一次状态变化都能被追踪。

  • action在严格模式下:本身不能直接修改state,必须通过commit mutation来改,如果action里写state.count = 10,同样会报错,这也符合设计逻辑:action是“指挥”,负责统筹逻辑;mutation是“执行者”,负责单纯改状态,职责必须分开。

举个错误案例:如果在action里直接改state,严格模式下会报错:

actions: {
  badAction({ state }) {
    state.count = 10; // 严格模式下报错!action不能直接改state
  }
}

正确做法是在action里commit mutation:

actions: {
  goodAction({ commit }) {
    commit('SET_COUNT', 10); // 正确,通过mutation改state
  }
}

实际开发中的协作:mutation和action怎么配合?

理解区别后,还要知道怎么在项目里配合着用,比如做一个“点赞”功能,流程应该是这样:

  1. 组件触发action:用户点击“点赞”按钮时,调用this.$store.dispatch('likeArticle', articleId)
  2. action处理异步与逻辑:在action里调接口记录点赞(异步),成功后触发mutation改状态:
    actions: {
      async likeArticle({ commit }, articleId) {
        const res = await axios.post(`/article/${articleId}/like`);
        if (res.data.success) {
          commit('INCREMENT_LIKE', articleId); // 调用mutation改状态
        }
      }
    }
  3. mutation修改state:在mutation里找到对应文章,更新点赞数:
    mutations: {
      INCREMENT_LIKE(state, articleId) {
        const article = state.articles.find(a => a.id === articleId);
        article.likeCount++;
      }
    }

这里action负责“和后端交互 + 决定是否修改状态”,mutation负责“单纯的状态更新”,分工明确后,代码维护性更高:如果以后要加点赞动画、埋点,都能塞到action里;如果要改状态更新逻辑(比如同时改点赞数和用户积分),只需要改mutation或者新增mutation,action不用动。

记住这张“区别表”

最后整理个对比表,方便快速记忆:

维度 mutations actions
核心职责 直接修改state(唯一合法入口) 处理异步/复杂逻辑,提交mutation
操作类型 同步操作(必须) 异步、同步都支持
触发方式 this.$store.commit() this.$store.dispatch()
直接改state? 可以(且只有这里能合法改) 不可以(必须通过commit mutation)
严格模式约束 仅允许通过它修改state 不能直接改state,需走mutation

刚学Vuex时,mutation和action像“双胞胎”,但实际职责、用法、约束完全不同,mutation管同步改状态,action管异步和逻辑协调”,写代码时先想清楚操作性质,选对工具,逻辑自然更清晰~ 下次开发遇到状态管理,别再把这俩搞混啦~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门