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

Javascript 带有输入处理程序的Vue组件v模型,javascript,vue.js,eventemitter,Javascript,Vue.js,Eventemitter,我正在尝试为Vue.js中的一个元素创建一个包装器组件 组成部分: <template> <div> <input v-bind="$attrs" :value="value" @input="input" /> ... </div> <template> Vue.component("my-input", { inheritAttrs: false, props: ['value'], me

我正在尝试为Vue.js中的一个元素创建一个包装器组件

组成部分:

<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" />
这就是我在$emitinput事件中遇到问题的地方。我得到以下错误:

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

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

如果我将组件的输入方法更改为发出$event而不是$event.target.value,那么新代码似乎可以工作,但是模型不会更新,而是更新为InputEvent而不是实际值

我不确定我需要做什么。

试试看

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

当您$emit'input'并且该值绑定到文本输入的v型时,的值将更新为您所发射的任何值。在$emit'input'、$event.target.value的情况下,它是您正在发射的文本的值。该值将在父级中被截取,正如v-model有效地执行以下操作:

这意味着的值将绑定回,实际上不会对输入中的值进行更改。但是,如果您$emit'input',$event,那么v-model仍然会捕获传递的任何值,并用它更新的值。在本例中,它将是实际的输入事件对象,如您所说

如果您不想使用绑定到模型的输入事件,则可以始终使用。然后,您可以$emit'input',$event,而不影响v-model值,相反,您可以从$emit'custom-event',$event.target.value更新v-model。当您$emit'input'并且该值绑定到文本输入的v-model时,该值将更新为您发出的值。在$emit'input'、$event.target.value的情况下,它是您正在发射的文本的值。该值将在父级中被截取,正如v-model有效地执行以下操作:

这意味着的值将绑定回,实际上不会对输入中的值进行更改。但是,如果您$emit'input',$event,那么v-model仍然会捕获传递的任何值,并用它更新的值。在本例中,它将是实际的输入事件对象,如您所说

如果您不想使用绑定到模型的输入事件,则可以始终使用。然后,您可以$emit'input'、$event,而不影响v-model值,而是从$emit'custom-event'、$event.target.value更新v-model,只需直接从父级分配它们,而不必创建代理 const MyInput=Vue.extend{ 名称:“MyInput”, 模板:“ins”, 数据{return{valid:true}}, 方法:{validateev{this.valid=ev.target.value.length<1;this.$listeners.inputev} } const App=Vue.extend{ 组成部分:{ 我的输入 }, 模板:“myinput”, 数据{return{val:'test'}}, 方法:{insev{console.logev.target.value} } 新Vue{ 名称:'根', 渲染:h=>hApp }$mountapp; 输入{背景:红色} .valid{背景:绿色!重要} 直接从父级分配它们,而不是创建代理 const MyInput=Vue.extend{ 名称:“MyInput”, 模板:“ins”, 数据{return{valid:true}}, 方法:{validateev{this.valid=ev.target.value.length<1;this.$listeners.inputev} } const App=Vue.extend{ 组成部分:{ 我的输入 }, 模板:“myinput”, 数据{return{val:'test'}}, 方法:{insev{console.logev.target.value} } 新Vue{ 名称:'根', 渲染:h=>hApp }$mountapp; 输入{背景:红色} .valid{背景:绿色!重要}
我试图使我的组件成为旧输入字段的替代品。基本上,除了出于设计目的将组件更改为我的自定义组件外,我不想弄乱旧的事件和代码。您发出的是值,而不是事件,因此@input只接收值,而不是$event。这就是为什么会出现错误:值未定义。你不能两全其美我明白。但是,如果我发出该事件,那么模型就会出错。您是否建议我不能创建一个自定义组件,除了使用典型的输入事件处理程序外,还可以使用此发射器适当地更新模型?我相信,在这种情况下,您必须将现有代码更新到上述版本,或者发出其他内容,例如@update,但这也需要您更新现有的代码,我不确定您还有什么其他选择。我正在尝试使我的组件成为旧输入字段的替代品。基本上,除了出于设计目的将组件更改为我的自定义组件外,我不想弄乱旧的事件和代码。您发出的是值,而不是事件,因此@input只接收值,而不是$event。那是
这就是为什么会出现错误:值未定义。你不能两全其美我明白。但是,如果我发出该事件,那么模型就会出错。您是否建议我不能创建一个自定义组件,除了使用典型的输入事件处理程序外,还可以使用此发射器适当地更新模型?我相信,在这种情况下,您必须将现有代码更新到上述版本,或者发出其他内容,例如@update,但这也需要你更新你现有的代码,我不确定你还有什么其他选择。好吧,我刚开始考虑这个问题。实际上,您是说我更新我的组件以包含model:{prop:value,event:custom event},然后在我的组件的输入方法中,我必须使用正确的$event或$event.target.value发出输入和自定义事件。我想它似乎起作用了。出于某种原因,我的一个字段直到第二次按键时才更新,但我认为这是另一个问题。@Quantastical是的,您需要两个单独的$emit事件来正确地保持值同步,我相信,但我认为这是在@Quantastical之外保持现有代码不变的唯一方法编辑问题或问一个新问题,如果你不明白的话,我可以看看另一个问题好的,我刚开始研究这个问题。实际上,您是说我更新我的组件以包含model:{prop:value,event:custom event},然后在我的组件的输入方法中,我必须使用正确的$event或$event.target.value发出输入和自定义事件。我想它似乎起作用了。出于某种原因,我的一个字段直到第二次按键时才更新,但我认为这是另一个问题。@Quantastical是的,您需要两个单独的$emit事件来正确地保持值同步,我相信,但我认为这是唯一一种方法,你可以在@Quantastical之外保持现有代码不变,编辑问题或问一个新问题,如果你不明白的话,我可以看看另一个问题谢谢。这是有道理的。我的简化示例遗漏了一个重要的细节,这使我无法这样做……除了传递任何事件处理程序之外,我的自定义组件还需要能够在输入上调用自己的内部方法来处理验证内容。不过,这是一个没有这些细节的有效答案。@Quantastical更改了它的答案。这是有道理的。我的简化示例遗漏了一个重要的细节,这使我无法这样做……除了传递任何事件处理程序之外,我的自定义组件还需要能够在输入上调用自己的内部方法来处理验证内容。虽然没有这些细节,但这是一个有效的答案。@Quantastical更改了它