Javascript 如何将项目推送到 Vuejs 中数据对象的数组中?Vue 似乎没有在看 .push() 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52235847/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 04:57:19  来源:igfitidea点击:

How do I push items into an array in the data object in Vuejs? Vue seems not to be watching the .push() method

javascriptlaravel-5vue.jsvuejs2vue-reactivity

提问by Travis Hohl

I am attempting to add objects into an array I declared in Vue instance data object. I can set the values in the state's purchase object, but when I push data into the orders queue array, the empty array is not populated. The function is being triggered, but the array does not update.

我试图将对象添加到我在 Vue 实例数据对象中声明的数组中。我可以在状态的购买对象中设置值,但是当我将数据推送到订单队列数组时,不会填充空数组。正在触发函数,但数组未更新。

Here is my form:

这是我的表格:

<form
  v-on:submit.prevent="queuePurchase"
  class="form-inline row"
  id="order-creation-form"
  method="POST"
>

  @csrf
  <autocomplete-field
    sizing="col-xs-12 col-sm-3 col-md-3"
    name="customer"
    label="Customer"
    :data="{{ json_encode($customers) }}"
    v-on:setcustomer="setCustomer($event)"
  ></autocomplete-field>

  <div class="col-xs-12 col-sm-3 col-md3 form-group d-flex flex-column align-items-start">
    <label for="phone">Product</label>
    <select
      v-model="purchase.product"
      class="form-control w-100"
      name="product"
      aria-describedby="productHelpBlock"
      required
    >
      @foreach ($products as $product)
        <option :value="{{ json_encode($product) }}">
          {{ $product->name }}
        </option>
      @endforeach
    </select>
    <small id="productHelpBlock" class="form-text text-muted">
      Select a product
    </small>
  </div>

  <div class="col-xs-12 col-sm-3 col-md-3 form-group d-flex flex-column align-items-start">
    <label for="phone">Quantity</label>
    <input
      v-model="purchase.quantity"
      type="number"
      min="1"
      name="product"
      class="form-control w-100"
      aria-describedby="productHelpBlock"
      required
    >
    <small id="productHelpBlock" class="form-text text-muted">
      Product quantity
    </small>
  </div>

  <div class="form-group">
    <button type="submit" class="btn btn-success icon-button d-flex">
      <i class="material-icons">add</i>
      <span>&nbsp;&nbsp;  Q U E U E</span>
    </button>
  </div>
</form>

And here is my javascript:

这是我的javascript:

require("./bootstrap");
window.Vue = require("vue");

Vue.component("queue-table", require('./components/QueueTable.vue'));
Vue.component("autocomplete-field", require('./components/AutocompleteField.vue'));

const purchaseApp = new Vue({
    el: "#purchase-app",

    data() {
        return {
            queue: [],
            purchase: {
                product: null,
                customer: null,
                quantity: null
            }
        }
    },

    methods: {
        setCustomer: function(customerObj) {
            this.purchase.customer = customerObj;
        },

        queuePurchase: function() {
            this.queue.push( this.purchase );
        }
    }
});

Could someone please explain what & why it is happening?

有人可以解释一下这是什么以及为什么会发生吗?

回答by Travis Hohl

The push()method ought to add purchaseobjects to the queuearray, but as @FK82 pointed out in his comment, push()is adding multiple references to the same purchaseobject. This means that if you change the object by increasing the quantity, every purchase's quantityproperty will be updated.

push()方法应该将purchase对象添加到queue数组中,但正如@FK82 在他的评论中指出的那样,push()正在添加对同一purchase对象的多个引用。这意味着如果您通过增加 来更改对象quantity,则每个purchasequantity属性都会更新。

You can give that a try here:

你可以在这里试一试:

const exampleComponent = Vue.component("example-component", {
  name: "exampleComponent",
  template: "#example-component",
  data() {
    return {
      queue: [],
      purchase: {
        product: null,
        customer: null,
        quantity: null
      }
    };
  },
  methods: {
    queuePurchase() {
      this.queue.push( this.purchase );
    }
  }
});

const page = new Vue({
  name: "page",
  el: ".page",
  components: {
    "example-component": exampleComponent
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js"></script>
<template id="example-component">
  <div>
    <p>The Queue has {{ this.queue.length }} items.</p>
    <input
      v-model="purchase.quantity"
      type="number"
      min="1"
      name="product"
      placeholder="Quantity"
    >
    <button @click="queuePurchase">
      Add to Queue
    </button>
    <pre>{{ JSON.stringify(this.queue, null, 2) }}</pre>
  </div>
</template>

<div class="page">
  <example-component></example-component>
</div>

Instead of push()ing a reference to the same purchaseobject, try creating a shallow copy with Object.assign({}, this.purchase)or by using the spread operator. Here's an example that uses the spread operator and then push()es the copy onto the queue:

与其使用push()对同一purchase对象的引用,不如尝试Object.assign({}, this.purchase)使用展开运算符或通过使用展开运算符来创建浅拷贝。这是一个使用扩展运算符然后push()将副本复制到 的示例queue

const exampleComponent = Vue.component("example-component", {
  name: "exampleComponent",
  template: "#example-component",
  data() {
    return {
      queue: [],
      purchase: {
        product: null,
        customer: null,
        quantity: null
      }
    };
  },
  methods: {
    queuePurchase() {
      this.queue.push({...this.purchase});
    }
  }
});

const page = new Vue({
  name: "page",
  el: ".page",
  components: {
    "example-component": exampleComponent
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js"></script>
<template id="example-component">
  <div>
    <p>The Queue has {{ this.queue.length }} items.</p>
    <input
      v-model="purchase.quantity"
      type="number"
      min="1"
      name="product"
      placeholder="Quantity"
    >
    <button @click="queuePurchase">
      Add to Queue
    </button>
    <pre>{{ JSON.stringify(this.queue, null, 2) }}</pre>
  </div>
</template>

<div class="page">
  <example-component></example-component>
</div>