Варианты товаров в корзине покупок Vue добавляются в корзину, но товар в корзине изменяется вместо добавления нового товара
У меня есть приложение vue версии "^2.6.11" с vuex, где я добавляю товары в корзину. У моих товаров есть вариации, такие как цвет, поэтому перед добавлением в корзину у меня есть два условия, сравнивающие цвет и идентификатор продукта.
product.productId == item.productId && product.colour == item.colour
Цвет выбирается из поля выбора, свойство продукта устанавливается с выбранным цветом при изменении события из поля выбора.
this.item.colour = event.target.value
Проблема в том, что он обновляет текущий товар в корзине, даже если цвет изменился, например:
В поле выбора отображается золото, нажимается кнопка "Добавить в корзину", и в корзину добавляется золотой предмет.
Поле выбора изменится на серебристое, компонент продукта изменит свой цвет на серебристый и нажата кнопка "добавить в корзину".
Текущее количество товара в корзине изменится на 2, а его цвет изменится на серебристый.
Странно то, что когда я перехожу к оформлению заказа и нажимаю кнопку "Назад", добавление в корзину работает так, как я хочу, путем добавления нового варианта элемента в корзину, однако, когда я добавляю еще один вариант после этого, он работает. как это было в первый раз.
Я надеюсь в этом есть смысл. Я не понимаю, почему это не работает, до нажатия кнопки возврата.
Я не могу настроить Jsfiddle или фрагмент кода, потому что здесь очень много компонентов, работающих вместе, поэтому я добавлю часть своего кода ниже.
// Product.vue
<template>
<div>
<b-col>
<b-card
v-bind:title="product_type"
v-bind:img-src="imagePath"
img-alt="Image"
img-top
tag="article"
style="max-width: 15rem;"
class="mb-2">
<b-card-text>{{ product_type }}</b-card-text>
<div class="form-group">
<label for="colourSelect">Please select a colour</label>
<select @change="onChange($event)">
<option v-for="item in metal_colour" v-bind:key="item">
{{ item }}
</option>
</select>
</div>
<div class="clearfix">
<div class="price pull-left" v-bind:key="price">€{{ price }}</div>
<div class="text-right">
<b-button @click="addToCart" variant="primary">Add to cart</b-button>
...
</template>
<script>
export default {
name: 'Product',
props: {
productId: Number,
imagePath: String,
product_type: String,
metal_colour: Array,
price: Number,
qty: Number
},
data() {
return {
item: {
productId: this.productId,
imagePath: this.imagePath,
product_type: this.product_type,
price: this.price,
colour: 'Gold',
qty: 1
}
}
},
methods: {
addToCart() {
this.$store.commit('addToCart', this.item)
this.$bvModal.show('modal-1')
},
onChange(event) {
this.item.colour = event.target.value
}
}
}
</script>
// store/index.js Vuex
...
mutations: {
addToCart(state, item) {
let found = state.inCart.find(
product =>
product.productId == item.productId && product.colour == item.colour
)
if (found) {
found.qty++
} else {
state.inCart.push(item)
}
}
},
...
Для своей корзины покупок я использую модальное окно, и элементы перечислены ниже:
// Cart.vue
<div>
<b-table striped :items="this.$store.state.inCart">
<template v-slot:cell(imagePath)="data">
<img :src="data.value" class="thumb" alt="product" />
{{ data.imagePath }}
</template>
</b-table>
</div>
<div slot="modal-footer">
<router-link to="/checkout">
<b-button variant="primary" @click="$bvModal.hide('modal-1')">
Checkout
</b-button>
</router-link>
<b-button class="modalBtn" variant="primary" @click="$bvModal.hide('modal-1')">
Continue Shopping
</b-button>
</div>
1 ответ
Ты использовал this
> this.$store.state.inCart
в <template>
разметка, должна быть просто $store.state.inCart
но это все равно должно было сигнализировать об ошибке и никогда не сработать.
<b-table striped :items="$store.state.inCart">
Возможно, у вас проблемы с реактивностью, попробуйте вместо этого:
import {mapState} from 'vuex'
computed: {
...mapState(['inCart'])
}
<b-table striped :items="inCart">
Наконец, когда вы добавляете товар в корзину, вам нужно добавить КОПИЮ item
объект, потому что вы передаете объект по ссылке и получаете неожиданное поведение в результате выполнения state.inCart.push(item)
.
Есть два варианта:
1) import (импорт) lodash
> import { copy } from 'lodash'
и использовать copy(item)
2) JSON.parse(JSON.stringify(item))
выглядит грязно, но быстро.
Эти два подхода отменят ссылку на объект.
Чтобы уточнить, вы можете выполнить этот процесс копирования внутри своего vuex
addToCart
метод:
addToCart(state, item) {
let found = state.inCart.find(
product => product.productId === item.productId && product.colour === item.colour
)
if (found) {
found.qty++
} else {
// Clone the object.
const insert = JSON.parse(JSON.stringify(item))
state.inCart.push(insert)
}
}