带有输入处理程序的 Vue 组件 v-model

Vue component v-model with input handler

我正在尝试为 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") 事件中遇到的问题。我收到以下错误:

Cannot read property 'value' of undefined

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

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

我不确定我需要做什么。

尝试

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

当您 $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-model 值,而是从 $emit('custom-event', $event.target.value)

更新 v-model

直接从父级分配它们而不是创建代理

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>