在vuex中更新state时,为什么将异步方法写在actions中,而不是mutations,这是为什么?

vuex中更新state的方法

首页,在 vuex 中只有 mutations 可以更新state

  • commit 一个 mutation,mutation 负责更改 state
  • dispatch 一个 action,在 action 中 commit 一个 mutation

所以按照上述使用方法,我们在使用时,如果不涉及异步操作,可以直接 commit 一个 mutation 去更改 state,如果有异步就需要将异步方法写在 dispatch 中,然后在 dispatch 中commit mutation 去更改 state

我们从源码角度来回答这个问题,以下代码来自 vuex 源码,做了部分提示警告逻辑的删减,不影响整体逻辑,vue源码
// 这个就是 Store 类的 commit 方法
function commit (_type, _payload, _options) {
    // check object-style commit
    const {type, payload, options} = unifyObjectStyle(_type, _payload, _options)
    // 定义mutation对象,type 其实就是我们要操作的 mutation 的方法名, payload 是参数(载荷)
    const mutation = { type, payload }
    // entry 就是要被执行的 mutation 方法
    const entry = this._mutations[type]
    
    // 省略了一些中间不影响逻辑的代码
    
    // 注册一些回调函数,可以看到 mutation 方法(entry)最终是在这个回调函数中执行,直接就执行结束,没有任何的 return 以及 异步处理,这样也就是说在 commit 中不可以写异步逻辑
    this._withCommit(() => {
        entry.forEach(function commitIterator (handler) {
            handler(payload)
        })
    })
    this._subscribers
    .slice() // shallow copy to prevent iterator invalidation if subscriber synchronously calls unsubscribe
    .forEach(sub => sub(mutation, this.state))
}
function dispatch (_type, _payload) {
    // check object-style dispatch
    const {type,payload} = unifyObjectStyle(\type, _payload)
    // 定义 action 对象,type 是 actions 对象中的一个属性,payload 是载荷
    const action = { type, payload }
    // 待执行的 action 方法
    const entry = this._actions[type]
    try {
        this._actionSubscribers
        .slice() // shallow copy to prevent iterator invalidation if subscriber synchronously calls unsubscribe
        .filter(sub => sub.before)
        .forEach(sub => sub.before(action, this.state))
    } catch (e) {}
    
    // 在这里执行了 action 方法,并将结果用 Promise.all 方法处理
    const result = entry.length > 1
    ? Promise.all(entry.map(handler => handler(payload)))
    : entry[0](payload)
    
    // 这里的 result.then 执行完以后会 return 一个结果出去(其实就是我们自己调用的异步逻辑的结果)
    return result.then(res => {
        try {
            this._actionSubscribers
            .filter(sub => sub.after)
            .forEach(sub => sub.after(action, this.state))
        } catch (e) {}
        return res
    })
}
问题:
  1. 可以在mutations和actions里写异步请求,并被外部组件调用。但是在mutations里的异步请求成功后不能更新state,actions里的异步请求成功后可以commit调用mutations去更新state

  2. 如果我把异步函数写在外部组件里,请求成功后commit调用mutations更新state也是可以的

解答:
  1. 在组件中执行异步操作,在异步的回调中执行commit也可以,但是一般不这么做,理由是:state状态更新逻辑是可复用的,但是如果把这部分逻辑写在了组件内,比如写在了组件A中,这时候另外一个组件B也需要更新这个状态,你就需要把组件A中的那段异步代码复制到组件B中,这个不是一个合理的方式(代码冗余,应该将公共逻辑抽离出来),虽然可以这么做,但是不推荐。

  2. 从字面意思来看你是想在一个mutation写异步逻辑?然后在异步的回调中commit另外一个更新数据的mutation?说实话没有人这么做,也没必要这儿做,但是可以理解你的执着,这个是可以的,但是你需要在commit第一个mutation的时候在载荷(payload)中把commit对象传递进来,然后payload.commit(‘mutation2’, payload2)。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值