【问题标题】:Calling two mutations from the same action从同一个动作中调用两个突变
【发布时间】:2017-05-02 19:53:53
【问题描述】:

我正在使用Vuex 商店将所有商品保存在购物车中。

商店有两个动作:

  • getCartContent,在页面加载时调用(从后端获取初始内容,然后从会话中检索数据)
  • addToCart,由<Products> 组件在用户单击添加到购物车按钮时调度。

这两个都调用了各自的突变(具有相同的名称),因为您不应该直接从组件内部调用突变。

这是商店的样子:

const store = new Vuex.Store({
	state: {
		items: [],
	},

	mutations: {
		getCartContent(state, data){
			axios.get('/api/cart').then(response => {
				state.items = response.data;
			});
		},

		addToCart(state, data){
			axios.post('/api/cart/add', {
				item_id: data.item,
			});
		}
	},

	actions: {
		getCartContent(context){
			context.commit('getCartContent');
		},

		addToCart(context, data){
			context.commit('addToCart', {item: data.item});
		}
	}
});

这按预期工作,但是现在当一个项目被添加到购物车时(从组件内调度到 addToCart 操作),我希望它在之后调用 getCartContent 突变,以便它从后端获取新的项目列表。

我尝试从同一个操作中提交第二个突变,如下所示:

actions: {
    // ...
 
	addToCart(context, data){
		context.commit('addToCart', {item: data.item});
		context.commit('getCartContent');
	}
}

但这并不总是有效,有时它会获取项目但并非总是如此。

我还尝试在分派 addToCart 操作之后立即从组件本身分派 getCartContent 操作,但这是同样的问题。

我该如何解决这个问题?

【问题讨论】:

  • 可以在组件内调用commit,没有问题。为异步代码保留操作。

标签: vue.js vuex


【解决方案1】:

您的axios 调用是异步的,这意味着当您的getCartContent 突变触发时,您的addToCart 突变可能不一定完成。因此,有时getCartContent 没有返回您之前告诉axios 发送帖子请求立即 的项目也就不足为奇了。

您应该将异步调用移至 vuex 操作:

actions: {
  getCartContent(context, data) {
    axios.get('/api/cart').then(response => {
      state.items = response.data;
      context.commit('getCartContent', response.data), 
    });
  },
  addToCart(context, data) {
    axios.post('/api/cart/add', {
      item_id: data.item,
    }).then(() => {
      context.commit('addToCart', data.item)
    })
  },
}

您的变更应该只对模块状态进行简单、直接的更改:

mutations: {
  getCartContent(state, items) {
    state.items = items;
  },
  addToCart(state, item) {
    state.items.push(item);
  }
}

上面的解释假设不是在每个 POST 请求之后发出 get('/api/cart') 请求,而是通过将数据推送到 state.items 属性来跟踪项目。

但是,如果您真的想在添加项目后发出 GET 请求,您可以在 POST 请求完成后去掉 addToCart 突变和 dispatch getCartContent 操作:

addToCart(context, data) {
  axios.post('/api/cart/add', {
    item_id: data.item,
  }).then(() => {
    context.dispatch('getCartContent');
  })
},

【讨论】:

  • 非常感谢,这很有意义。您的编辑来得及时,我想再次调用 getCartContent 因为后端计算了其他一些东西(例如:总计)。我将重新调度 addToCart 中的 getCartContent 操作。
猜你喜欢
  • 2018-03-22
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
  • 2018-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多