我有一份订单位置清单。每个职位都有产品名称,数量,价格,总和。此外,还有一些输入字段,其中包含以百分比和绝对值(例如美元)为单位的预付款项。我使用吸气剂进行绝对预付款。因此,为了编辑输入的绝对值并使百分数为最新,我必须通过百分数值在存储中对其进行更新,即我必须计算百分数值,其中绝对值等于新的百分数(只需在输入字段中输入)。但是,这是一个问题:当我在绝对值的输入字段中输入数字时,百分比的计算会导致对绝对吸气剂的重新计算,从而使回车符返回到开头(好的,这里可以使用反跳功能),但是我也觉得这是错误的,并且发生了一些违反逻辑的事情。
对不起,一团糟。代码:
store.js:
Vue.use(Vuex);
let product = {
order: 1,
name: '',
size: '',
content: '',
price: 0,
number: 1,
discount: '',
guarantee: 0,
promotion: 0,
location: '',
sum: 0,
};
export default new Vuex.Store({
strict: true,
state: {
products: [
Object.assign({}, product),
],
form: {
prepaymentInPercent: 100,
},
},
getters: {
total(state) {
return +(state.products.length > 0 && state.products.reduce(function (acc, cur) {
return acc + cur.sum;
}, 0));
},
rest(state, getters) {
return Math.round(getters.total - getters.prepaymentInRub);
},
prepaymentInRub(state, getters) {
return Math.round(getters.total * state.form.prepaymentInPercent / 100);
},
},
mutations: {
[ADD_PRODUCT](state, product) {
state.products.push(product);
},
[UPDATE_PRODUCT](state, {updatedProduct, index}) {
state.products.splice(index, 1, updatedProduct);
},
[DELETE_PRODUCT](state, index) {
state.products.splice(index, 1);
},
[UPDATE_FORM](state, updatedFormFields) {
state.form = Object.assign({}, state.form, updatedFormFields);
},
},
actions: {
addProduct({commit}) {
let newProduct = Object.assign({}, product, {'order': product.order++});
commit(ADD_PRODUCT, newProduct);
},
updateProduct: _.debounce(function ({commit}, {product, index}) {
let updatedProduct = Object.assign({}, product);
commit(UPDATE_PRODUCT, {updatedProduct, index});
}, 200),
deleteProduct({commit, state}, index) {
state.products.length > 1 && commit(DELETE_PRODUCT, index);
},
updatePrepaymentInRub({commit, getters}, rubles) {
let prepaymentInPercent = Math.round(rubles / getters.total * 100);
commit(UPDATE_FORM, {prepaymentInPercent});
},
},
});
和
OrderForm.vue
<template>
<form>
<label>Prepayment, %
<input id="prepaymentInPercent" type="number" min="0" max="100" v-model="prepaymentInPercent">
</label>
<label>Prepayment, rubles
<input id="prepaymentInRub" min="0" type="number" :max="total" v-model="prepaymentInRubles">
</label>
</form>
</template>
<script>
import {UPDATE_FORM} from "../mutation-types";
import {mapGetters} from 'vuex';
export default {
name: "OrderForm",
computed: {
'prepaymentInRubles': {
get() {
return this.$store.getters.prepaymentInRub;
},
set(value) {
this.$store.dispatch('updatePrepaymentInRub', value);
}
},
...mapGetters(['total']),
'prepaymentInPercent': {
get() {
return this.$store.state.form.prepaymentInPercent;
},
set(value) {
return this.$store.commit(UPDATE_FORM, {
'prepaymentInPercent': value
});
}
}
},
}
</script>
ProductRow.vue
<template>
<tr>
<td colspan="2" class="id">{{indexFrom1}}</td>
<Editable v-model="product.name"/>
<Editable v-model="product.size"/>
<Editable v-model="product.content"/>
<Editable v-model.number="product.price"/>
<Editable v-model.number="product.number"/>
<Editable v-model="product.discount"/>
<td>
<select v-model.number="product.promotion">
<option selected value="0">No</option>
<optgroup label="forNewsettlers">
<option value="5">-5%</option>
<option value="10">-10%</option>
<option value="15">-15%</option>
</optgroup>
</select>
</td>
<td>{{sum}}</td>
<Editable v-model.number="product.guarantee"/>
<td>
<select v-model="product.location">
<option selected value="SERVICE">Service</option>
<option value="STOREHOUSE">Storehouse</option>
<option value="SO">Special Order</option>
<option value="from 1st shop">exhibition sample from 1st shop</option>
</select>
</td>
<td>
<span class="table-remove" @click="removeProduct(index)">Удалить</span>
</td>
</tr>
</template>
<script>
import Editable from './EditableCell';
export default {
components: {
Editable,
},
name: 'ProductRow',
props: {
initialProduct: Object,
index: Number,
},
data() {
return {
product: Object.assign({}, this.initialProduct),
};
},
computed: {
sum() {
let discountedPrice = this.isDiscountInPercent(this.product.discount) ?
this.product.price * this.getCoeffFromPercent(this.product.discount) :
this.product.price - this.product.discount;
let priceWithPromotion = discountedPrice * this.getCoeffFromPercent(this.product.promotion);
let sum = Math.round(priceWithPromotion * this.product.number);
return sum > 0 ? sum : 0;
},
indexFrom1() {
return this.index + 1;
},
},
methods: {
getCoeffFromPercent(percent) {
return 1 - parseInt(percent) / 100;
},
isDiscountInPercent(discount) {
return ~discount.indexOf('%') ? true : false;
},
removeProduct(index) {
this.$store.dispatch('deleteProduct', index);
}
},
watch: {
sum() {
this.product.sum = this.sum;
},
product: {
handler(product) {
this.$store.dispatch('updateProduct', {
product: product,
index: this.index,
});
},
deep: true,
},
},
};
</script>
答案 0 :(得分:1)
我认为您的逻辑很好。状态中的一个值具有两个不同的表示形式和可能的突变。
为避免出现光标问题,我将更改您正在输入中监听的事件。请记住,v-model="prepaymentInPercent"
等效于@input="prepaymentInPercent = $event.target.value" :value="prepaymentInPercent"
。 input事件会在每次字符更改时触发,但是您可以将其替换为change事件,它将在模糊或输入时触发。例如@change="prepaymentInPercent = $event.target.value" :value="prepaymentInPercent"
事实证明,有一个lazy修饰符会自动执行此操作,因此您只需将.lazy
添加到v模型中即可。