我可以从 Vuex 存储中的突变之一调用提交吗?
Can I call commit from one of mutations in Vuex store
我有一个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
}
我想从突变中调用突变:SET_CATEGORIES
:SET_PRODUCTS
,但这给了我错误:
projectFilter.js:22 未捕获(在承诺中(引用错误:未定义提交(...
应该采取什么正确的方法。我尝试了store.commit
和this.commit
,但这些也给出了类似的错误。
如果你绝对必须提交两个突变,为什么不从一个动作中去做呢?操作不必执行异步操作。您可以在操作中解构 commit 方法,就像处理状态一样,如下所示:
commitTwoThings: ({commit}, payload) => {
commit('MUTATION_1', payload.thing)
commit('MUTATION_2', payload.otherThing)
}
作为记录。要从突变方法调用其他突变,请执行以下操作:
const mutations = {
mutationOne(state, payload){
this.commit("mutationTwo", payload)
},
mutationTwo(state, payload){
console.log("called from another mutation", payload)
}
}
当你已经在做一个突变时,没有办法commit
另一个突变。突变是更改状态的同步调用。在一个突变中,您将无法实施另一个突变。
以下是 Vuex 的 API 参考: https://vuex.vuejs.org/en/api.html
如您所见,突变处理程序仅接收state
和payload
,仅此而已。因此,您commit
undefined
.
在上述情况下,您可以将 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})
},
// ...
}
编辑:请参考下面的答案,由Daniel S. Deboer提供。正确的方法是从一个动作中提交两个突变,如他的回答中所述。
若要在突变之间共享代码,必须创建一个执行工作的新函数,然后可以重用该函数。幸运的是,突变只是普通的旧函数,我们可以随心所欲地传递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)
}
如果我有一些影响多个突变之间状态的通用代码,我必须在所有突变上复制相同的代码?或者有更好的方法可以做到这一点?
阅读关于 Actions 的 Vuex 文档,很清楚它们的用途。
- 提交突变而不是改变状态
- 可以包含任意异步操作
操作可以(不是必须(包含异步代码。事实上,下面的例子是正确的
increment (context) {
context.commit('increment')
}
我认为使用操作执行多个突变没有任何问题。
在你的情况下,你应该考虑只有一个突变,即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来改变。
我偶然发现了一个非常相似的问题,对我来说的解决方案是使用 vuex getter :
https://vuex.vuejs.org/en/getters.html您的类别实际上是您产品的"计算"版本。将类别作为获取器可以让您使它们与产品保持同步,并避免重复商店中的数据。
为了回答标题中的问题,我保留了原始答案。
丹尼尔·巴克马斯特解决方案的替代方案:
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)
}
}
如您所见,您可以直接调用突变本身。(正如丹尼尔所说,它们毕竟只是普通的函数(
我相信这是对原始问题的更合适的答案:这是一种没有代码重复或额外函数的组成突变的实际方式
我更喜欢调用mutations.SET_CATEGORIES(state)
而不是:- 从人工操作调用 2 个不同的提交- 或者在突变内部进行commit()
,因为它使单元测试更加困难。
const mutations = {
SET_PRODUCTS: (state, response) => {
state.products = response.data.products
mutations.SET_CATEGORIES(state)
},
SET_CATEGORIES: (state) => {
state.categories = state.products.map(product => product.category)
}
}
我的观点是,你不需要在 VueToolbox 中看到SET_CATEGORIES
。无论如何,时间旅行应该有效。如果我错了,请纠正我。
首先,将 Vue 按钮分配给一个变量:主要.js:
export const app = new Vue({
router,
vuetify,
store,....
然后将 "app" 变量导入到定义突变的 js 文件中:在模块中.js:
import { app } from "../../main";
您现在可以将其用作"app.$store.commit":
mutations: {
[AUTH_SET_TOKEN]: () => {
app.$store.commit(USER_SUCCESS, params );
},...
我认为
从另一个突变调用突变是一个坏主意,因为很难调试状态和组件
const mutations = {
mutationOne(state, payload){
this.commit("mutationTwo", payload)
},
mutationTwo(state, payload){
console.log("called from another mutation", payload)
}
}
但是你可以写简单的函数,函数可以重用
function mysecondfn(state,payload){
{
// do your stuff here
}
const mutations = {
mutationOne(state, payload){
mysecondfn(state,payload)
},
}
另一个对我有用的解决方案:
this._mutations.mutationFunction[0]()
import spreeApi from '../../gateways/spree-api'
// initial state
const state = {
products: [],
categories: []
}
// mutations
const mutations = {
SET_PRODUCTS: (state, {response,commit}) => { // here you destructure the object passed to the mutation to get the response and also the commit function
state.products = response.data.products
commit('SET_CATEGORIES') // now the commit function is available
},
SET_CATEGORIES: (state) => {
state.categories = state.products.map(function(product) { return product.category})
}
}
const actions = {
FETCH_PRODUCTS: ({commit}, filters) => { // here you destructure the state to get the commit function
return spreeApi.get('products').then(response => commit('SET_PRODUCTS', {response,commit})) // here you pass the commit function through an object to 'SET_PRODUCTS' mutation
}
}
export default {
state,
mutations,
actions
}
这应该可以解决它。您可以从操作将提交注入到突变中,以便可以从突变提交。希望这有帮助
您可以访问所有 Vuex
this.app.store.commit("toast/show", {
mssg:this.app.i18n.t('order.ordersummary.notifymessage'),
type: "danger",
});
在 Vuex 访问 $i 18N
this.app.i18n.t('order.ordersummary.notifymessage')
使用这个
const mutations = {
SET_PRODUCTS: (state, response) => {
state.products = response.data.products
this.commit('SET_CATEGORIES')
},
SET_CATEGORIES: (state) => {
setCategories(state)
}
}
在 Vuex 中,突变是负责修改 Vuex 存储状态的同步函数。虽然突变不能直接调用其他突变,但您可以通过利用操作来实现所需的行为。
下面是如何使用操作从另一个突变调用一个突变的示例:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++;
},
doubleIncrement(state) {
state.count += 2;
},
},
actions: {
incrementAndDouble({ commit }) {
commit('increment');
commit('doubleIncrement');
},
},
});
export default store;
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="incrementAndDouble">Increment and Double</button>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
computed: {
...mapState(['count']),
},
methods: {
...mapActions(['incrementAndDouble']),
},
};
</script>
- 如何在 API 调用后和 if 语句中启用提交按钮
- angularjs-控制器在表单提交时未调用
- 为什么我的ajax在提交用@HtmlRenderPartial加载的表单时只调用fire一次
- 调用DOM提交方法时未激发jQuery提交事件
- 父操作可防止在 ember.js 中调用提交操作
- BootStrap Django Jquery Modal在Ajax调用提交时未关闭
- 如何使用 jquery ajax 调用提交表单时更改表单操作
- 如果表单无效,是否调用提交
- 表单提交和javascript函数调用提交按钮点击在spring mvc
- 我可以从 Vuex 存储中的突变之一调用提交吗?
- 不显眼的验证甚至在我的javascript调用提交之前就失败了
- 如何在代码编写器中调用提交函数
- 我如何做一个ajax调用提交,并确保html5验证也发生
- 递归地调用提交的JQuery表单
- 解析HTML并使用jquery调用提交按钮
- 从jquery调用提交按钮函数
- 通过原型 Ajax 调用提交二进制数据
- JQuery:通过 AJAX 调用提交包含多个字段的表单
- 条形码阅读器调用提交函数在我的形式
- 使用javascript提交数据,而不是调用提交按钮