具有输入处理程序的Vue组件v模型

时间:2019-07-09 13:02:51

标签: javascript vue.js eventemitter

我正在尝试为Vue.js中的<input/>元素创建包装器组件。

组件:

<template>
  <div>
    <input v-bind="$attrs" :value="value" @input="input" />
    ...
  </div>
<template>

Vue.component("my-input", {
   inheritAttrs: false,
   props: ['value'],
   methods: {
     input($event): void {
       this.$emit("input", $event.target.value)
     }
  }
})

用法:

<my-input v-model="myModel" />

这似乎很好。通过输入事件处理程序,通过发出目标元素值来更新模型。

但是,现在我正在尝试将此组件与一些现有代码一起使用:

<my-input v-model="myModel2" @input="something = $event.target.value" />

这是我在$emit("input")事件上遇到麻烦的地方。我收到以下错误:

  

无法读取未定义的属性“值”

因此,我的$emit发出了,现在现有的@input="something..."事件处理程序无法正确引用$event

如果我将组件的input方法更改为发出$event而不是$event.target.value,则新代码似乎可以正常工作,但是模型无法得到更新被更新为 InputEvent 而不是实际的 value

我不确定该怎么做。

3 个答案:

答案 0 :(得分:1)

尝试

<my-input v-model="myModel2" @input="value => something = value" />

答案 1 :(得分:1)

当您$emit('input')并将值绑定到文本输入的v-model时,<input>的值将更新为您发出的任何值。对于$emit('input', $event.target.value),它是您发出的<input>中文本的值。该值将在父级中被拦截,就像v-model那样:<my-input :value="inputValue" @input="inputValue = $event">

这意味着<input>的值将绑定回到<input>(有效地导致输入中的值不变)。但是,如果您$emit('input', $event),则v-model仍将捕获传递的任何值,并使用它更新<input>的值。如您所说,在这种情况下,它将是实际的输入事件对象。

如果您不想使用与模型相关的input事件,则可以始终使用custom v-model event。然后,您将能够$emit('input', $event)而不会影响v模型的值,而是从$emit('custom-event', $event.target.value)

更新v模型。

答案 2 :(得分:1)

只需直接从父级分配它们,而不创建代理

const MyInput = Vue.extend({
  name: 'MyInput',
  template: '#ins',
  data(){return{valid: true}},
  methods: {validate(ev){this.valid = ev.target.value.length < 1 ;this.$listeners.input(ev)}}
})

const App = Vue.extend({
  components: {
    MyInput
  },
  template: '#myinput',
  data(){return{val: 'test'}},
  methods: {ins(ev){console.log(ev.target.value)}}
})

new Vue({
  name: 'root',
  render: h => h(App)
}).$mount("#app");
input {background: red}
.valid{background:green !important}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app"></div>

<template id="ins">
  <input v-bind="$attrs" @input="validate" :class="{valid:valid}"/>
</template>

<template id="myinput">
    <my-input v-model="val" @input="ins" />
</template>