vue.js - 错误:不要在突变处理程序之外改变 vuex 存储状态
问题描述
场景
我正在使用 Vuex,在其中存储一些数据,在我的情况下是工单详细信息。最初,我有一张有一系列折扣的票,它是空的。一旦我点击“添加折扣”按钮,我就会安装名为“testDiscount”的组件,该组件在已安装的挂钩中推动({"code": "Foo", "value":"Boo"})
商店中特定票的折扣数组中的第一个对象。当我尝试在此组件中输入输入框(更改其状态)时出现问题,其中出现错误“不要在突变处理程序之外改变 Vuex 存储状态。”。我怎样才能最好地处理这个?
测试.vue
<template>
<div>
<test-component v-for="(t, key) in tickets" :key="key" :ticket-key="key" :tid="t.id"></test-component>
</div>
</template>
<script>
import TestComponent from "~/components/testComponent.vue";
export default {
layout: "noFooter",
components: {
"test-component": TestComponent,
},
data() {
return {
tickets: this.$store.state.ticketDiscount.tickets,
};
},
mounted() {
if (this.tickets.length == 0) {
this.$store.commit("ticketDiscount/addTicket", {
id:
this.$store.state.ticketDiscount.tickets.length == 0
? 0
: this.$store.state.ticketDiscount.tickets[
this.$store.state.ticketDiscount.tickets.length - 1
].id + 1,
discount: [],
});
}
},
};
</script>
ticketDiscount.js
export const state = () => ({
tickets: []
});
export const mutations = {
addTicket(state, ticket) {
state.tickets.push(ticket);
},
addDiscount(state, property) {
state.tickets.find(ticket => ticket.id == property.id)[property.name].push(property.value);
}
测试组件.vue
<template>
<div>
<h3>Ticket number: {{ticketKey + 1}}</h3>
<button @click="showDiscount = true">Add discount</button>
<test-discount v-model="discount_" v-if="showDiscount" :tid="tid"></test-discount>
</div>
</template>
<script>
import testDiscount from "~/components/test-discount.vue";
export default {
components: {
testDiscount,
},
data() {
return {
showDiscount: false,
tid_: this.tid,
};
},
props: {
tickets: Array,
ticketKey: { type: Number },
tid: { type: Number, default: 0 },
},
methods: {
updateTicket() {
this.$emit("updateTicket", {
id: this.tid_,
value: {
discount: this.discount_,
},
});
},
},
mounted() {
this.$watch(
this.$watch((vm) => (vm.discount_, Date.now()), this.updateTicket)
);
},
computed: {
discount_: {
get() {
return this.$store.state.ticketDiscount.tickets.find(
(ticket) => ticket.id == this.tid
)["discount"];
},
set(value) {
// set discount
},
},
},
};
</script>
testDiscount.vue
<template>
<div class="container">
<div class="title">
<img src="~/assets/svgs/price_tag.svg" />
<span>Discount code</span>
{{ discounts }}
</div>
<div class="discount-container">
<div v-for="(c,idx) in discounts" class="discounts" :key="idx">
<div class="perc-input">
<input style="max-width: 50px;" v-model.number="c.discount" type="number" min="1" max="100" step="1" placeholder="10">
<div>%</div>
</div>
<input class="code-input" v-model="c.code" placeholder="Code">
<img src="~/assets/svgs/bin.svg" title="Delete code" @click="deleteCode(idx)" v-if="discounts.length > 1"/>
</div>
</div>
<span @click="newDiscount" class="add-another">+ Add another discount</span>
</div>
</template>
<script>
export default {
props: {
value: {
type: Array,
},
tid: { type: Number, default: 0 },
},
data() {
return {
discounts: this.value,
}
},
mounted() {
if (this.discounts.length == 0) {
this.newDiscount();
}
},
methods: {
newDiscount() {
this.$store.commit('ticketDiscount/addDiscount',
{
"id": this.tid,
"name": "discount",
"value": { code: null,discount: null }
});
},
deleteCode(index) {
this.discounts.splice(index, 1);
}
},
watch: {
discounts() {
this.$emit('input', this.discounts)
}
},
beforeDestroy() {
this.$emit('input', []);
}
}
</script>
解决方案
你不应该v-model
在这种情况下使用。
<input style="max-width: 50px;" v-model.number="c.discount" .../>
你可以设置值
<input style="max-width: 50px;" :value="c.discount" @change="handleValueChange" .../>
然后在handleValueChange
函数中提交仅针对该值进行更新的操作。
推荐阅读
- jsonschema - 如何使用 JSON 模式在两个同级对象中强制执行互斥属性?
- excel - VBA Excel - 即使工作表受到保护也使用 VBA
- python-3.x - 我将如何在 python 中创建一个程序来实现这一点?
- javascript - 传入 React 组件的 Annoymous 函数的 Typescript 接口
- html - 如何使用 Bootstrap 创建提升的表单?
- php - 如何仅使用 jquery 和 php 制作高效的 ajax 实时表单
- javascript - 通过将用户输入 onchange 传递给父组件来反应 Javascript 问题
- python - 如何计算和存储未知数量的输入Python
- ios - 检测 UISlider 何时开始和结束拖动
- css - 我想在滚动时停止导航栏中的 div 移动