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

Представьте, что вам нужно указать количество детей, которые у вас есть. Для каждого дочернего элемента будут отображаться текстовые поля имени и фамилии.

Вы можете изменить количество детей с помощью input [type = "number"] или вручную .

Зависимости:
vue @ 2

Вот мой HTML:

<div id="app">
  <form>
      <label for="childrenCount">Amount of children</label>

      <input
        type="number"
        id="childrenCount"
        min="0"
        v-model="amountOfChildren"
      />

    <template v-if="amountOfChildren > 0">
      <h2>Children</h2>

      <div
        v-for="(child, index) in children"
        :key="index">

        Child {{ index + 1 }}:

        <input
          type="text"
          placeholder="First name"
          v-model="child.firstName"
        />

        <input
          type="text"
          placeholder="Last name"
          v-model="child.lastName"
        />
      </div>
    </template>
  </form>
</div>

Вот мой код Vue:

<script>
  new Vue({
    el: '#app',

    data() {
      return {
        amountOfChildren: 0,

        form: {
          children: []
        }
      }
    },

    computed: {
      children() {
        this.form.children = [];

        for (let index = 0; index < this.amountOfChildren; index++)
          this.form.children.push({ firstName: '', lastName: '' });

        return this.form.children;
      }
    }
  });
</script>

При этом, если я увеличиваю / уменьшаю количество дочерних элементов, я теряю все изменения (из-за вычисляемого свойства). Есть ли способ достичь моей цели, используя только v-модель? Без кнопок и генерации событий?

Я пытался использовать наблюдателей и пользовательские методы, но безуспешно ...

Ожидаемая структура данных:

form: {
  "children": [
      { "firstName": "Jinny", "lastName": "Doe" },
      { "firstName": "James": "lastName": "Doe" }
  ]
}
1
Ilya Zhidkov 4 Дек 2020 в 00:24

1 ответ

Лучший ответ

Вы можете преобразовать children в метод и использовать вместо него обработчик событий @input:

new Vue({
  el: '#app',

  data() {
    return {
      form: {
        children: []
      }
    }
  },

  methods: {
    children(e) {
      const {
        children
      } = this.form;
      const popOrPush = e.target.value > children.length ? 'push' : 'pop';
      const difference = Math.abs(e.target.value - children.length);

      for (let i = 0; i < difference; i++) {
        this.form.children[popOrPush]({
          firstName: '',
          lastName: ''
        });
      }
    }
  }
});

Vue.config.productionTip = false;
Vue.config.devtools = false;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <form>
    <label for="childrenCount">Amount of children</label>

    <input type="number" id="childrenCount" min="0" @input="children" />

    <template v-if="form.children.length > 0">
      <h2>Children</h2>

      <div
        v-for="(child, index) in form.children"
        :key="index">

        Child {{ index + 1 }}:

        <input
          type="text"
          placeholder="First name"
          v-model="child.firstName"
        />

        <input
          type="text"
          placeholder="Last name"
          v-model="child.lastName"
        />
      </div>
    </template>
  </form>
</div>

ИЗМЕНИТЬ

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

Есть ли способ достичь моей цели, используя только v-модель? Без кнопок и выдачи событий?

Но я все равно оставлю это здесь на случай, если вы сочтете это полезным.

1
Daniel_Knights 3 Дек 2020 в 23:27