我可以从Vuex商店中的一个突变调用commit

Sau*_*abh 53 javascript vue.js 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
}
Run Code Online (Sandbox Code Playgroud)

我想调用变异:SET_CATEGORIES来自变异:SET_PRODUCTS,但这给了我错误:

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

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

小智 76

如果你绝对必须提交两个突变,为什么不从一个动作做到这一点?操作不必执行异步操作.您可以像处理状态一样对动作中的提交方法进行解构:

commitTwoThings: ({commit}, payload) => {
  commit('MUTATION_1', payload.thing)
  commit('MUTATION_2', payload.otherThing)
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么不呢?...使用 [vue-native-websocke](https://github.com/nathantsoi/vue-native-websocket#readme),您需要处理来自 ws 服务器的突变 (SOCKET_ONMESSAGE) 数据...他们也无法从突变中调用动作。 (3认同)
  • 是的,这应该是答案. (2认同)

Man*_*ani 34

当你已经进行了突变时,就无法进行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})
    },
    // ...
}
Run Code Online (Sandbox Code Playgroud)

编辑:请参阅Daniel S. Deboer提供的以下答案.正如他的回答所述,正确的方法是从单个动作中提交两个突变.

  • 我想知道为什么不允许从另一个突变中提交突变?一些突变可能是原子性的,它们应该被更大的突变功能使用.在当前版本中,由于此限制,应该有很多重复的代码. (4认同)

Dan*_*ter 23

要在突变之间共享代码,您必须创建一个执行工作的新函数,然后可以重复使用.幸运的是,突变只是普通的旧函数,我们可以根据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)
}
Run Code Online (Sandbox Code Playgroud)

  • 什么让你有那个想法?只要您只从突变中调用“setCategories”,就可以了。 (2认同)

Kub*_*ien 13

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

const mutations = {
    mutationOne(state, payload){
        this.commit("mutationTwo", payload)
    },
    mutationTwo(state, payload){
        console.log("called from another mutation", payload)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句,如果你的“modules”是命名空间的,即使它位于同一个文件下,你也必须通过“this.commit('modulesName/mutationName')”访问它,以防万一有人想知道。如果您需要更多信息,它总是一个很好的提醒,只需在突变中执行 `console.log(this)` ,它似乎拥有与 `Vue` 相同的实例,您也可以从它访问 `$route`那里。 (21认同)
  • 这是Vuex的新功能吗?令人惊讶的是,花了两年半的时间指出了正确的答案。 (4认同)
  • 我不太确定这是否被认为是最佳实践。然而,这个答案**直接回答了问题。**没有提供其他人通过“action”建议的替代方案。我已经测试过了,看起来效果很好。我认为这个答案应该放在最上面。如果有人有兴趣阅读更多证据,[Vuex Github - 请添加从另一个突变调用突变的功能 #907](https://github.com/vuejs/vuex/issues/907) 中已经讨论了此解决方案。 (3认同)

小智 9

如果我有一些影响多个突变之间状态的通用代码,我必须在我的所有突变上复制相同的代码?或者有更好的方法吗?

  • 沉默震耳欲聋.我也喜欢这个答案. (6认同)
  • 仅当您有答案时才发布答案。如果您想问什么,请创建一个新线程。 (2认同)

Wan*_*lli 5

阅读有关ActionsVuex文档,很清楚它们的用途。

  • 提交突变而不是改变状态
  • 可以包含任意异步操作

动作可以(不是必须)包含异步代码。其实下面的例子是正确的

increment (context) {
   context.commit('increment')
}
Run Code Online (Sandbox Code Playgroud)

使用动作执行多个突变时,我看不到任何问题。