Варианты товаров в корзине 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>


person rachaelcumiskey    schedule 02.04.2020    source источник
comment
Сделав здесь удар, попробуйте выйти из product.colour и item.colour во время их сравнения и попробуйте оператор тройного равенства для обоих, чтобы увидеть, не изменится ли что-нибудь. product.productId === item.productId && product.colour === item.colour ... эй, это JavaScript, мало ли   -  person Jeremy Anderson    schedule 02.04.2020


Ответы (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) импортируйте 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)

  }
}
person Marc    schedule 02.04.2020
comment
Спасибо за вашу помощь, быстрый и грязный метод у меня сработал. Я пытался создать новый объект для добавления в корзину, но раньше он не работал, но это JSON.parse сработало. Также спасибо за указание на эту проблему. - person rachaelcumiskey; 02.04.2020
comment
Вы также должны использовать оператор тройного равенства (===), как указал Джереми в комментариях. Тройное означает абсолютное равенство, двойное равенство - неуловимое совпадение и может привести к неожиданным результатам. - person Marc; 02.04.2020