带有输入处理程序的 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>
我正在尝试为 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)
直接从父级分配它们而不是创建代理
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>