Let's say I've created a custom component Comp.vue
that basically is an wrapped input element with a model-value
prop and @update="$emit('update:modelValue', $event.target.value)
.
It might look like this:
<template>
<div>
<label :for="name" class="block relative">
<div>
{{ label }}
</div>
<input
:name="name"
:type="type"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</label>
</div>
</template>
<script>
export default {
props: {
label: {
required: true,
type: String,
},
modelValue: {
required: false,
default: "",
type: [String, Number],
},
type: {
default: "text",
type: String,
},
name: {
required: false,
type: String,
default: "",
},
},
emits: ["update:modelValue"],
};
</script>
Now I've imported that component in App.vue.
Why does this work:
<Comp @change="doSth1()" />
<Comp @input="doSth2()" />
My custom Comp.vue
never emits any of those events.
I've created a custom playground that logs those events: Playground Link
UPDATE 2 to clarify the listening on native DOM events
The native DOM events are normally propagated to parent elements.
So, all normal HTML elements inside your Vue component are generating native DOM events and you can listen to them outside your component.
That's why beforeinput
event is triggering by the component if you have an input
element inside it.
Check the JavaScript: Understanding the Event Propagation for more details.
Since input
and change
are native DOM events, Vue listens to them automatically.
Please check the Vue docs: Directives, v-on and HTMLElement, input events
When used on a normal element, it listens to native DOM events only. When used on a custom element component, it listens to custom events emitted on that child component.
It looks like Vue still listens to native HTML input events by custom components.
See my UPDATE 2 above.
For example, there is also an beforeinput
event which is also fired automatically and listened by Vue. So you can add a directive for it also.
@beforeinput="beforeinputTriggered()"
UPDATE 1 to answer @Thibault
The changing of modelValue themself does not fire 'input/change' events. If we remove the HTML input element in the Comp.vue, then the 'beforeinput/input/change' events will be not fired.
Here is the proof: same component with a +1 button fires only the @update:modelValue
event.