首页 > 解决方案 > 对象的属性已更新,但没有新对象被推送到数组中(购物车、单个文件组件)

问题描述

我遇到了一个问题。我正在尝试编写购物车代码。我有 4 个组件:

ProductDetails 中的每个产品都有带有addToCart功能的按钮,该按钮作为参数 item 属性。每次我尝试向数组中添加一个新产品(对象)时,前一个可能会被新的替换。我使用 制作每个对象的深层副本Vue.util.extend,以便更新数量属性。这很好用。但是当我尝试将不同的项目添加到购物车数组时,前一个项目会消失并且新的项目会显示。我正在使用 EventBus,并且购物车从 ProductDetails 组件发送到 ShoppingCart 组件。

我通过使用这个 codepen 帮助了自己:https ://codepen.io/anon/pen/BEEwqd 一切正常。

我正在从本地(静态/products.json)获取数据。

我尝试将项目从 github 导入到 codesandbox 以使您的一切更轻松,但不知何故它无法按预期工作,因此我将链接粘贴到我的仓库:

https://github.com/rafalpyska/weeklywebdevchallange10

客厅.vue

<template lang="html">
  <div class="container">

      <transition-group tag="section" class="products" name="list">
        <Product
          v-for="item in dataToDisplay"
          :item="item"
          :key="item.id"
          @click.native="handleProductDetails(item)"
        />
      </transition-group>

    </main>

    <ProductDetails
      v-if="isProductDetailsOpen"
      :item="itemDetails"
      :data="data"
    />

</template>

<script>
  const API = '/static/products.json';

  export default {
    name: 'LivingRoom',
    data() {
      return {
        status: true,
        data: [],
        dataToDisplay: [],
        itemDetails: null,
      }
    },
    components: {
      Product,
      ProductDetails
    },
    created() {
      axios.get(API)
        .then((response) => {
          this.data = response.data[0].category[0];
          for (let key in this.data) {
            if (!this.data.hasOwnProperty(key)) continue;
            this.dataToDisplay = this.data[key];
          }
          this.status = false;
        })
    },
    methods: {
      handleProductDetails(item) {
        this.isProductDetailsOpen = true;
        this.itemDetails = item;
      }
    }

产品.vue

<template lang="html">
    <div>
      <p>class="products__name">{{ name }}</p>
      <p class="products__description">{{ description)</p>
      <p class="products__price">${{ price }}</p>
    </div>
</template>

<script>
  export default {
    name: "Product",
    props: {
      item: {
        required: true
      }
    },
    data() {
      return {
        name: this.item.title,
        description: this.item.description,
        price: this.item.price,
      }
    }
  };
</script>

产品详情.vue

<template lang="html">
  <section class="product-details">
    <h2 class="product__name">{{ name }}</h2>
    <label for="quantity">Quantity</label>
    <input class="input__quantity" id="quantity" max="10" min="1" name="quantity" type="number"
                     v-model.number="item.quantity">
    <button @click="addToCart(item)" class="btn">Add to cart</button>
  </section>
</template>

<script>
  import Vue from 'vue'
  import {EventBus} from "@/event-bus.js";

  export default {
    name: "ProductDetails",
    props: {
      item: {
        type: Object,
        required: true
      },
      data: {
        type: Object,
        required: true
      }
    },
    data() {
      return {
        cart: [],
        name: this.item.title,
        id: this.item.id,
        quantity: this.item.quantity
      }
    },
    methods: {
      addToCart(productToAdd) {
        let found = false;
        this.cart.forEach((item) => {
          if (item.id === productToAdd.id) {
            found = true;
            item.quantity += productToAdd.quantity;
          }
        });
        if (found === false) {
          this.cart.push(Vue.util.extend({}, productToAdd));
        }
        productToAdd.quantity = 1;
        EventBus.$emit('update-cart', this.cart);
      }
    }
  };
</script>

购物车.vue

<template lang="html">
        <div class="cart" v-for="item in cart">
          <div class="cart__product-info">
            <p></p>
            <p class="item__title">Product: {{ item.title }}</p>
            <p class="item__quantity">Quantity: {{ item.quantity }}</p>
          </div>
        </div>
      </div>
    </section>
</template>

<script>
  import {EventBus} from "@/event-bus.js";

  export default {
    name: "ShoppingCart",
    data() {
      return {
        cart: null
      }
    },
    created() {
      EventBus.$on('update-cart', (item) => {
        this.cart = item;
      });
    }
  }

产品.json

[
  {
    "category": {
      "0": {
        "title": "Living Room",
        "id": 1
        "products": {
          "0": {
            "title": "Red Seat",
            "id": 1,
            "description": "Armless Task Chair with Adjustable Height and Swivel Functionality. Comfortable 2 inches thick cushioned back and seat. 360 degrees swivel functionality. Pneumatic seat height adjustment. Upholstered in an easy to clean fabric. Dual wheel caster for any type of flooring",
            "price": "45",
            "image": "images/redseat.png",
            "quantity": 1
          },
          "1": {
            "title": "White Table",
            "id": 2,
            "description": "International Concepts Solid Wood Dining Table with Shaker Legs",
            "price": "350",
            "image": "images/whitetable.png",
            "quantity": 1
          }
        }
      }
    }
]

标签: vue.jsvuejs2vue-component

解决方案


cart: []每个总是一个空数组ProductDetails?所以当你把一个项目推到它上面时,最大长度是 1

一种可能的解决方案是更改update-cart侦听器

EventBus.$on('update-cart', (item) => {
  const newItem = item[0]
  this.cart = this.cart || []
  let found = false
  this.cart = this.cart.map(oldItem => {
    if (oldItem.id === newItem.id) {
      found = true
      return newItem
    }
    return oldItem
  })
  if (!found) {
    this.cart = this.cart.concat(item)
  }
});

推荐阅读