vuex API里面的action

行动

Action类似于变异,不同于在:

  • Action提交的是mutation,而不是直接更改状态。
  • Action可以包含任意异步操作。

注册一个简单的动作:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

动作函数接受一个与店内实例具有相同方法和属性的背景对象,因此你可以调用  context.commit 提交一个突变,或者通过  context.state 和  context.getters 来电子杂志状态和干将。

实践中,我们会经常用到ES2015的  参数解构  来简化代码(特别是我们需要调用  commit 很多次的时候):

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

分发行动

Action通过  store.dispatch 方法触发:

store.dispatch('increment')

乍一眼看上去感觉多此一举,我们直接分发突变岂不更方便?实际上并非如此,还记得  突变必须同步执行这个限制么?行动就不受约束!我们可以在行动内部执行异步操作:

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

Actions支持同样的载荷方式和对象方式进行分发:

// 以载荷形式分发
store.dispatch('incrementAsync', {
  amount: 10
})

// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

来看一个更加实际的购物车示例,涉及到调用异步API  和分发多重突变

actions: {
  checkout ({ commit, state }, products) {
    // 把当前购物车的物品备份起来
    const savedCartItems = [...state.cart.added]
    // 发出结账请求,然后乐观地清空购物车
    commit(types.CHECKOUT_REQUEST)
    // 购物 API 接受一个成功回调和一个失败回调
    shop.buyProducts(
      products,
      // 成功操作
      () => commit(types.CHECKOUT_SUCCESS),
      // 失败操作
      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
    )
  }
}

注意我们正在进行一系列的异步操作,并且通过提交突变来记录动作产生的副作用(即状态变更)。

在组件中分发行动

你在组件中使用  this.$store.dispatch('xxx') 分发动作,或者使用  mapActions 辅助函数将组件的方法映射为  store.dispatch 调用(需要先在根节点注入  store):

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

组合行动

Action通常是异步的,那么如何知道action什么时候结束呢?更重要的是,我们如何才能组合多个action,以处理更加复杂的异步流程?

首先,你需要明白  store.dispatch 可以处理被触发的动作的处理函数返回的承诺,并且  store.dispatch 仍旧返回Promise:

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

现在你可以:

store.dispatch('actionA').then(() => {
  // ...
})

在另外一个动作中也可以:

actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}

最后,如果我们利用  async / await,我们可以如下组合action:

// 假设 getData() 和 getOtherData() 返回的是 Promise

actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}

一个  store.dispatch 在不同模块中可以触发多个动作函数。在这种情况下,只有当所有触发函数完成后,返回的Promise才会执行。

猜你喜欢

转载自blog.csdn.net/weixin_41646716/article/details/80392049