【问题标题】:Vue component v-model with input handler带有输入处理程序的 Vue 组件 v-model
【发布时间】:2019-11-19 01:12:27
【问题描述】:

我正在尝试为 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 而不是实际的

我不确定我需要做什么。

【问题讨论】:

    标签: javascript vue.js eventemitter


    【解决方案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>

    【讨论】:

    • 谢谢。这确实有道理。我的简化示例遗漏了一个重要的细节,阻止我这样做......我的自定义组件除了可能传入的任何事件处理程序之外,还需要能够在输入时调用它自己的内部方法(用于处理验证内容)。这个不过,没有这些细节是一个有效的答案。
    • @Quantastical 改变了它
    【解决方案2】:

    当您 $emit('input') 并且该值与文本输入的 v-model 相关联时,&lt;input&gt; 的值将更新为您发出的任何内容。对于$emit('input', $event.target.value),它是您发出的&lt;input&gt; 中文本的值。该值将在父级中被截获,就像v-model 有效地做的那样:&lt;my-input :value="inputValue" @input="inputValue = $event"&gt;

    这意味着&lt;input> 的值将绑定回&lt;input&gt;(实际上不会更改输入中的值)。但是,如果您是$emit('input', $event),那么v-model 仍将捕获向上传递的任何值并用它更新&lt;input&gt; 的值。在这种情况下,正如您所说,它将是实际的输入事件对象。

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

    【讨论】:

    • 好的,我刚开始看那个。本质上,您是说我更新了我的组件以包含model: { prop: "value", event: "custom-event" },然后在我的组件的input 方法中,我必须使用正确的$event$event.target.value 发出inputcustom-event。我认为它似乎正在工作。由于某种原因,我的一个字段直到第二次按键才更新,但我认为这是另一个问题。
    • @Quantastical 是的,你需要两个单独的 $emit 事件来正确保持你的值同步我相信,但我认为这是你能够保持现有代码相同的唯一方法&lt;my-input&gt;之外的
    • @Quantastical 编辑问题或提出新问题,如果您无法弄清楚,我可以查看其他问题
    【解决方案3】:

    试试

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

    【讨论】:

    • 我正在尝试使我的组件成为旧输入字段的替代品。除了出于设计目的将组件更改为我的自定义组件之外,基本上不想弄乱旧的事件和代码。
    • 您发出的是值,而不是事件,所以@input 只接收值,而不是$event。这就是您收到错误的原因:value 未定义。你不能同时拥有它
    • 我明白这一点。但是,如果我发出事件,那么模型就会混乱。您是否建议我除了具有典型的输入事件处理程序之外,还不能创建使用此发射器来适当更新模型的自定义组件?
    • 我相信是这种情况,您必须将现有代码更新为上述代码,或发出其他内容 @update 例如,但这也需要您更新现有代码,我'我不太确定你还有什么其他选择。
    猜你喜欢
    • 2020-12-03
    • 2020-09-24
    • 1970-01-01
    • 2019-02-14
    • 2020-03-12
    • 2019-04-30
    • 2017-11-14
    • 2022-08-13
    • 2020-06-07
    相关资源
    最近更新 更多