Обновите несколько входов программно в vue - PullRequest
0 голосов
/ 02 апреля 2020

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

<template>
  <custom-input :value="contact.name" @input="event => contact.name = event.target.value" />
  <custom-input :value="contact.phone" @input="event => contact.phone = event.target.value" />
  <custom-input :value="contact.email" @input="event => contact.email = event.target.value" /> 
</template>

<script>
...
props: {
  contact: {
    type: Object,
    required: true
  }
},
watch: 
  "contact.name": function(value) {
    if (this.contact.name === "john") {
      this.contact.email = "john@email.com"
      this.contact.phone = "1111111111"
    } else if (this.contact.name === "ed") {
      this.contact.email = "ed@email.com"
      this.contact.phone = "2222222222"  
    }
  }
}

...
</script>

Я понимаю, что Vue это не нравится, потому что оно отделяет DOM от модели данных. Моей первой мыслью было использовать $refs, но это только для чтения. Какой правильный способ сделать это?

Еще одна мысль, которая у меня была, заключалась в том, чтобы установить значения name и phone для вычисляемых свойств. Проблема в том, что он не отслеживается на форме в родительском компоненте.

Это также может быть связано с моим неправильным пониманием "двустороннего" связывания. Я всегда считал, что форма - это один способ, а данные в скрипте компонента - другой, а это не так. Итак, как же иначе?

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

<template>
  <custom-input :value="contact.name" @input="event => contact.name = event.target.value" />
  <custom-input ref="phone" :value="contact.phone" @input="event => contact.phone = event.target.value" />
  <custom-input ref="email" :value="contact.email" @input="event => contact.email = event.target.value" /> 
</template>

<script>
...
props: {
  contact: {
    type: Object,
    required: true
  }
},
watch: 
  "contact.name": function(value) {
    if (this.contact.name === "john") {
       this.$refs.email.$emit("input", "john@email.com")
       this.$refs.phone.$emit("input", "111111111111")
    } else if (this.contact.name === "ed") {
       this.$refs.email.$emit("input", "ed@email.com")
       this.$refs.phone.$emit("input", "222222222222")
    }
  }
}

Похоже, это тоже не работает. Облом.

Редактировать

Исправлены синтаксические ошибки

Редактировать 2

Показано, что input действительно было отдельный дочерний компонент

1 Ответ

2 голосов
/ 02 апреля 2020

Я только что заметил, что вы пытаетесь изменить значение props, которое запрещено Vue. Все дочерние компоненты не могут изменять данные в props, передаваемые из родительского элемента, поскольку это затрудняет понимание потока данных. Вы можете прочитать больше об этом на официальном сайте: https://vuejs.org/v2/guide/components-props.html#One -Way-Data-Flow

Именно поэтому Vue также имеет data, которая является локальной частной памятью, которая может быть измененным компонентом.

Таким образом, чтобы решить вашу проблему, вам необходимо скопировать данные в props в data на дочернем компоненте, когда он смонтирован, и вместо этого изменить значение data.

Это обновленный пример кода (Codepen также обновляется), который делает именно то, что вы хотите.

Шаблон:

<div id="app">
  <div>
    <my-form :contact="contact"></my-form>
  </div>
</div>

Javascript:

Vue.component('my-form', {
  data() {
    return { name: '', phone: '', email: '' }
  },
  props: {
    contact: { type: Object, required: true }
  },
  mounted() {
    this.name = this.contact.name;
    this.phone = this.contact.phone;
    this.email = this.contact.email;
  },
  template: `
    <div>
      <input v-model="name" />
      <input v-model="phone"/>
      <input v-model="email"/>
      <p>
        value of input: {{ JSON.stringify({ name, phone, email }) }}
      </p>
    </div>
  `,
    watch: {
      name(value) {
        if(value === 'john') {
           this.phone = '123456';
           this.email = 'test@gmail.com';
        }
      }
    }
});
new Vue({
  el: '#app',
  data() {
    return { contact: { name: 'initial name', phone: '123456', email: 'initial.email@gmail.com' } }
  }
})

И мой обновленный код ручки: https://codepen.io/aptarmy/pen/PoqgpNJ

...