Избегайте изменения реквизитов во вложенных формах

#javascript #vue.js

#javascript #vue.js

Вопрос:

Допустим, у меня есть форма, разделенная на две части, каждая из которых сообщается с родительской формой через реквизиты. Как мне избежать изменения реквизитов, переданных из родительской формы?


ParentForm.vue

 <template>
  <div>
    <AddressForm :form-data="formData.address" />
    <OtherForm :form-data="formData.other" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      formData: {
        address: {
          address_no: "",
          country: "",
        },
        other: {
          remarks: "",
        },
      },
    };
  },
};
</script>

 

AddressForm.vue

 <template>
  <div>
    <input v-model="formData.address_no" />
    <input v-model="formData.country" />
  </div>
</template>

<script>
export default {
  name: "AddressForm",
  props: { formData: { type: Object, required: true } },
};
</script>
 

OtherForm.vue

 <template>
  <div>
    <textarea v-model="formData.remarks" />
  </div>
</template>

<script>
export default {
  name: "OtherForm",
  props: { formData: { type: Object, required: true } },
};
</script>
 

Изменение значения полей ввода в AddressForm.vue or OtherForm.vue вызовет предупреждение о мутации реквизита. Я хотел знать, как мне взаимодействовать вверх / вниз с формами без изменения реквизита?

Я придумал возможные решения, но я не знаю, какое из них мне выбрать (а также как его реализовать)

  • Клонируйте formData реквизит created() и ссылайтесь v-model на локальный клонированный formData вместо реквизита. Затем наблюдайте за клонированием formData и излучайте каждый раз, когда значение менялось.
  • Привязка с использованием v-model вместо реквизита

Ответ №1:

Создайте дочерние формы в качестве пользовательских входных данных, используя v-model вместо передачи реквизитов:

AddressForm.vue

 <template>
  <div>
    <input :value="value.address_no" @input="$emit('input',{...value,address_no:$event.target.value)" />
    <input :value="value.country" @input="$emit('input',{...value,country:$event.target.value)" />
  </div>
</template>

<script>
export default {
  name: "AddressForm",
  props: { value: { type: Object, required: true } },
};
</script>
 

Другая форма :

 <template>
  <div>
    <textarea :value="value.remarks" @input="$emit('input',{...value,remarks:$event.target.value)"/>
  </div>
</template>

<script>
export default {
  name: "OtherForm",
  props: { value: { type: Object, required: true } },
};
</script>
 

в родительском компоненте :

     <AddressForm v-model="formData.address" />
    <OtherForm v-model="formData.other" />
 

Комментарии:

1. Спасибо, у меня есть еще один вопрос — выдача при каждом @input не очень идеальна для меня (я работаю над очень большой формой). Есть ли способ оптимизировать это?

2. с удовольствием, добавьте lazy модификатор в v-model директиву, например <OtherForm v-model.lazy="formData.other" />

Ответ №2:

Вы можете присвоить beforeMount() этим реквизитам некоторые значения данных, а затем $emit их обратно.
Очевидно, v-model следует ссылаться на свойства, определенные в data() .

Комментарии:

1. Спасибо, можете ли вы привести пример?