Как правильно обновить массив потомок родительского в Vue JS - PullRequest
0 голосов
/ 12 мая 2018

Итак, я изучаю Vue.js, и после небольшой борьбы я (каким-то образом) получил следующий фрагмент кода , работающий .Я знаю, что если это работает, это не глупо, но, тем не менее, я хотел бы получить помощь о том, как улучшить мой код, поскольку я сомневаюсь, что я использую правильный подход.

Следующий код позволяет пользователю добавлять несколько экземпляров компонента Item, нажимая кнопку.Ввод поля имени в Item передается объекту, который вставляется в массив, который отправляется обратно в родительский компонент.

Моя главная проблема с этим подходом состоит в том, что массив items используется всеми экземплярами Item как опора, что не нужно.Однако я не могу придумать другое решение, потому что я знаю, как обмениваться данными между компонентами, передавая их как опору и обновляя.Я также читал, что реквизиты должны обновляться только родителем, поэтому я предполагаю, что я также нарушаю это правило.

Может ли кто-нибудь научить меня лучшему подходу?

Родительский код

<template>

    <div class="items">
         <div v-for="n in itemCount">
            <Item :count="n" :items="items"  />
         </div>
    </div>

    <button @click="addItem">Add item</button>

</template>

<script>
    import Item from './../components/Item'; //the child 

    export default {

        components: {
            Item
        },

        data() {
            return {
                itemCount: 1,
                items: [],
            }
        },

        methods: {
            addItem() {
                this.itemCount ++;
            }
        }

    }
</script>

Ребенок

<template>

    <div class="item">
        <label>Item name</label>
        <input type="text" v-model="name" @input="update(count)" />    
    </div>

</template>

<script>
    export default {

        props: ['items','count'],

        data() {
            return {
                name: '',
            }
        },

        methods: {

            createItem(index) {
                return {
                    index: index-1,
                    name: this.name,
                }
            },

            update(index) {
                const item = this.createItem(index);
                this.$set(this.items, index-1, item);
            },
        }
    }
</script>

1 Ответ

0 голосов
/ 12 мая 2018

Вы вправе чувствовать себя некомфортно с первоначальной реализацией.В идеале дочерний компонент не должен предполагать ничего о своем родителе.В этом случае дочерний компонент просто отображает <label> и <input>, чтобы пользователь мог ввести имя элемента.Это не должно знать или заботиться, что есть многократные пункты.Вот один из способов создания такого компонента.Он эффективно определяет свою собственную модель и просто отображает эту модель в <input>:

Vue.component('custom-item', {
  props: {
    value: String
  },
  template: `
    <div class="custom-item">
      <label>Item name</label>
      <input
        type="text"
        :value="value"
        @input="$emit('input', $event.target.value)"
      >
    </div>
  `
});

. Затем родительский компонент просто передает соответствующий v-model дочернему элементу: (Обратите внимание, что я переместил <button> внутри корневого элемента, поскольку шаблон не может иметь более одного прямого дочернего элемента.)

Vue.component('custom-items', {
  data() {
    return {
      items: []
    };
  },
  methods: {
    addItem() {
      items.push({
        index: items.length,
        name: ""
      });
    }
  },
  template: `
    <div class="custom-items">
      <div v-for="item in items">
        <custom-item v-model="item.name"/>
      </div>
      <button @click="addItem">
        Add item
      </button>
    </div>
  `
});

Этот код использует ту же структуру для объектов items, но кажется маловероятным, что вам действительно нужносвойство .index, в этом случае items может быть просто массивом строк, а не объектов.

Кроме того, если вы не занимаетесь стилизацией, вам на самом деле не нужен <div> Оберните вокруг каждого пользовательского элемента, так что вы можете упростить это для простоты:

    <div class="custom-items">
      <custom-item
        v-for="item in items"
        v-model="item.name"
      />
      <button @click="addItem">
        Add item
      </button>
    </div>

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

...