【问题标题】:Update multiple inputs programmatically in vue在 vue 中以编程方式更新多个输入
【发布时间】:2020-07-14 00:43:23
【问题描述】:

我有一个表单,当另一个字段被更新时,我需要更新多个其他表单字段。例如,我有一个联系人姓名,根据联系人姓名,我需要更新电子邮件和电话的值。

<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实际上是一个单独的子组件

【问题讨论】:

  • 除了:value 和@input 的不必要分离(只使用v-model),我认为您在这里所做的没有任何问题。也许我误解了你的问题?
  • @DecadeMoon 可悲的是它不起作用。应该吗?
  • 没关系,我重新阅读了您的代码并发现了一些语法错误。看我的回答。
  • 您所做的那些编辑清除了一切,谢谢。我仍然认为v-model 可以(并且应该)在这里使用,但是由于我们正在处理自定义组件,您可能不会收到它发出的input 事件的本机事件对象。你能确认一下吗?
  • @DecadeMoon 我怎么知道何时收到该事件?我知道它是基于 Vue 控制台触发的,但它会为 Error in v-on handler: "TypeError: Cannot read property 'value' of undefined" 引发错误

标签: javascript vue.js frontend


【解决方案1】:

我刚刚注意到您正在尝试修改 Vue 禁止的 props 的值。所有子组件都不能修改从父组件传来的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

【讨论】:

  • 太棒了!让我尝试实现这一点。
  • @user3162553 我已经测试过了,它可以工作。请告诉我它是否适合你。
  • 它确实有效,但在预选状态时我无法更改电话或电子邮件值。这应该是默认值。不过我忘了提,所以无论如何我都会赞成。
  • @user3162553 我刚刚更新了答案中的代码示例,使phone 和email 可更新。我的 Codepen 也更新了,请查看。
  • @user3162553 我的代码已更新。我更新的答案中解释了您的代码不起作用的问题原因。这是因为您试图修改 Vue 不允许的 props 的值。通过props 传输的数据是单向绑定。请重新阅读我的答案,查看更新后的 Codepen,更新您的代码,并告诉我它现在是否有效。
猜你喜欢
  • 2012-12-26
  • 1970-01-01
  • 1970-01-01
  • 2014-06-02
  • 2018-04-24
  • 2014-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多