Vue JS V-для V-Bind не является уникальным

Я пытаюсь создать форму, в которой у меня есть список выбора (полученный из API), и пользователь может добавлять элементы в отдельный массив из этого списка. Новый массив также визуализируется через v-for и использует v-модель для редактирования некоторых дополнительных данных.

Например, у меня есть заранее определенный список товаров / услуг, который будет отображаться в блоке выбора. Теперь пользователь может выбрать один из этих продуктов и добавить их в счет. После добавления (переданного в новый массив) пользователь должен иметь возможность внести некоторые дополнительные изменения.

<select class="form-control" v-model="selectedServiceId">
    <option v-for="service in services" :value="service._id">{{service.name}}</option>
</select>

<button type="button" class="btn btn-primary" v-on:click="addService">Add</button>

добавить метод обслуживания:

addService() {
    for (var i = 0; i < this.services.length; i++) {
      if (this.services[i]._id == this.selectedServiceId) {
        this.services_goods.push(this.services[i])
        break;
      }
    }
  }

И теперь я хочу сделать список, в который я вставил:

<ul>
          <li v-for="(item, key) in services_goods">
            <span>{{item.name}}</span>
            <label for="itemPrice">Price €
              <input id="itemPrice" v-model="item.price">
            </label>
            <label for="itemQty">Quantity
              <input type="number" min="1" id="itemQty" v-model="item.quantity">
            </label>
            <div>
              <button type="button" v-on:click="removeService(item._id)">X</button>
            </div>
          </li>
        </ul>

все хорошо, пока я не добавлю один и тот же товар дважды и не попытаюсь изменить цену для одного из них - это изменит цену для обоих.

1 ответ

Решение

Причина, по которой он меняет цену для обоих, заключается в том, что они являются одним и тем же объектом. Когда вы вставляете объект в массив, значение в массиве является ссылкой на объект. У вас есть две ссылки на один и тот же объект.

Каждый объект, который вы вставляете в массив, должен быть заново создан, а содержимое скопировано из выбранного элемента.

new Vue({
  el: '#app',
  data: {
    selectedServiceId: null,
    services: [{
        _id: 1,
        price: 1,
        quantity: 1,
        name: 'First'
      },
      {
        _id: 2,
        price: 2,
        quantity: 2,
        name: 'Second'
      }
    ],
    services_goods: []
  },
  methods: {
    addService() {
      const foundGood = this.services.find((s) => s._id == this.selectedServiceId);

      // Object.assign copies an object's contents
      this.services_goods.push(Object.assign({}, foundGood));
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<div id="app">
  <select class="form-control" v-model="selectedServiceId">
    <option v-for="service in services" :value="service._id">{{service.name}}</option>
</select>

  <button type="button" class="btn btn-primary" v-on:click="addService">Add</button>
  <ul>
    <li v-for="(item, key) in services_goods">
      <span>{{item.name}}</span>
      <label for="itemPrice">Price €
              <input id="itemPrice" v-model="item.price">
            </label>
      <label for="itemQty">Quantity
              <input type="number" min="1" id="itemQty" v-model="item.quantity">
            </label>
      <div>
        <button type="button" v-on:click="removeService(item._id)">X</button>
      </div>
    </li>
  </ul>
</div>

Другие вопросы по тегам