我可以从Vuex存储中的一种变异中调用提交吗

我有一个vuex商店,如下所示:

import spreeApi from '../../gateways/spree-api'
// initial state
const state = {
  products: [],
  categories: []
}

// mutations
const mutations = {
 SET_PRODUCTS: (state, response) => {
   state.products = response.data.products
   commit('SET_CATEGORIES')
 },
 SET_CATEGORIES: (state) => {
   state.categories = state.products.map(function(product) { return product.category})
 }

}

const actions = {
 FETCH_PRODUCTS: (state, filters) => {
   return spreeApi.get('products').then(response => state.commit('SET_PRODUCTS', response))
 }
}

export default {
  state,
  mutations,
  actions
}

我想称呼mutation:SET_CATEGORIESfrom突变:SET_PRODUCTS,但这给了我错误:

projectFilter.js:22未捕获(在承诺中)ReferenceError:未定义提交(…)

什么应该是正确的方法来做到这一点。我尝试了store.committhis.commit,但是这些也给出了类似的错误。

Stafan前端2020/03/11 10:26:16

编辑:我偶然发现了一个非常相似的问题,对我来说,解决方案是使用vuex getter:https ://vuex.vuejs.org/en/getters.html
您的类别实际上是产品的“计算”版本。将类别用作获取者可以使它们与产品保持同步,并避免重复存储中的数据。

为了回答标题中的问题,我保留了原始答案。
Daniel Buckmaster解决方案的替代方案:

const mutations = {
 SET_PRODUCTS: (state, response) => {
   state.products = response.data.products
   this.SET_CATEGORIES(state)
 },
 SET_CATEGORIES: (state) => {
   state.categories = state.products.map(product => product.category)
 }
}

如您所见,您可以直接调用突变本身。(正如Daniel所说的,毕竟它们只是简单的函数)
我相信这是对原始问题的更合适的答案:这是在没有代码重复或额外功能的情况下构成突变的一种实际方法。

Pro乐2020/03/11 10:26:16

在您的情况下,您应该考虑只有一个突变,即SET_PRODUCTS。

// mutations
const mutations = {
 SET_PRODUCTS: (state, response) => {
   state.products = response.data.products
   state.categories = state.products.map(function(product) { return product.category})
 }
}

您永远不需要单独调用SET_CATEGORIES。想想看!只有更改产品,类别才会发生变化。产品只能通过SET_PRODUCTS进行更改。

MandyL2020/03/11 10:26:16

如果我有一些通用代码会影响多个突变之间的状态,我是否必须在所有突变上重复相同的代码?还是有更好的方法做到这一点?

飞云小哥2020/03/11 10:26:16

作为记录。要从突变方法中调用其他突变,请执行以下操作:

const mutations = {
    mutationOne(state, payload){
        this.commit("mutationTwo", payload)
    },
    mutationTwo(state, payload){
        console.log("called from another mutation", payload)
    }
}
猪猪小小2020/03/11 10:26:16

要在突变之间共享代码,必须创建一个新功能来执行工作,然后可以重用该功能。幸运的是,变异只是普通的旧函数,我们可以随意传递state参数,所以这很容易做到。

例如:

const mutations = {
 SET_PRODUCTS: (state, response) => {
   state.products = response.data.products
   setCategories(state)
 },
 SET_CATEGORIES: (state) => {
   setCategories(state)
 }
}

function setCategories(state) {
  state.categories = state.products.map(product => product.category)
}
ㄏ囧囧ㄟ2020/03/11 10:26:16

当您已经在做突变时,就无法进行commit其他突变。变异是一种同步呼叫,会改变状态。在一个突变中,您将无法进行另一个突变。

这是Vuex的API参考:https ://vuex.vuejs.org/en/api.html

如您所见,变异处理程序仅接收statepayload仅接收所以你得到commitundefined

在上述情况下,您可以将PRODUCT和CATEGORIES设置为同一更改处理程序的一部分,作为一次提交。您可以尝试以下代码是否有效:

// mutations
const mutations = {
    SET_PRODUCTS_AND_CATEGORIES: (state, response) => {
        state.products = response.data.products
        state.categories = state.products.map(function(product) { return product.category})
    },
    // ...
}

编辑:请参阅下面的答案,由丹尼尔·S·德博尔提供正确的方法是一次执行两个突变,如他的回答所述。