2.5.1+
https://jsfiddle.net/bvyo2yra/
See the minimal reproduction.
Previous to 2.5.1, v-on="$listeners"
could be used in combination with more specific event handlers to create components that could transparently pass events to an element inside them. This worked because the more specific listeners (e.g. @input="$emit('input', $event.target.value)
) were called _after_ the more generic listeners with v-on="$listeners
.
In 2.5.1, these higher priority listeners are now triggered first, so that if the listener sets a value, it will set the correct value, _then_ the incorrect value, breaking v-model
.
The breaking change was made to solve another issue, so it's probably not ideal to just revert the change. And actually, even the previous behavior was slightly undesirable, as it emitted the same event twice.
To fix both issues, I would actually expect the more specific event binding (e.g. @input
) to _replace_ the listener of the same name from v-on
with the object syntax. The more specific listener would then take responsibility for emitting an event at the correct time. That allows the user full, explicit control over the order in which local handlers and handlers from the parent are called.
How does that sound to others?
The replacing behavior would also be a breaking change though. I think preserving both is more semantically correct, and among the two, the current behavior in 2.5.1+ is the more reasonable (disregarding combined usage with v-model
).
I think the goal really should be how can we make v-model
and v-on="$listeners"
work together while retaining the semantically correct behavior. There is currently a workaround I mentioned here, although it's not very straightforward and requires understanding of the internals.
Yeah, I'm not a fan of the workaround - it feels a bit hacky. What would you think about suggesting the following pattern instead?
<input
:value="value"
v-on="{
...$listeners,
input: event => $emit('input', event.target.value)
}"
>
@chrisvfritz that's actually reasonable. It's explicitly overwriting the parent input listener.
Excellent. I've updated the docs and this issue can probably be closed, but I agree that long-term, it really would be nice for v-model
listeners just automatically work.
Ideally, v-model
listeners on components could:
Event
...event.target.tagName
to choose the appropriate element listenerv-model
on components, where the payload is assumed to be the new value
Most helpful comment
Yeah, I'm not a fan of the workaround - it feels a bit hacky. What would you think about suggesting the following pattern instead?