Hi team,
Maybe there should be a way to let components emit caught native events.
In my case I'm writing a music player component, I want to allow users of my component to use .native modifier to listen native Media Events on my component, like
<music-player @play.native="handleOnPlay" />
We know that .native modifier listen to native events on the root element of the component, but in this case <audio> apparently can't be a root component.
There're also other common cases facing similar issue:
<input>I know I can catch internal native events and emit a custom event like <audio @play="e => $emit('play', e)"> then let user do <music-player @play="handleOnPlay">, but I just feel using .native directly is more intuitive.
Possible forms
.native modifier listens to not only the root elementv-emit-native on a non-root HTML element that lets the element emit its native events to outer .native listeners$emit.native(e) method on Vue instanceYou can use $listeners to capture all v-on bindings of the component and selectively forward them to the native HTML element. See Binding Native Events to Components.
@Justineo Oh I haven't learned about that. It's a great feature.
I just tried it out but it didn't seem to work.
<music-player @timeupdate.native="handleTimeUpdate" />
// music-player.vue
<audio v-on="$listeners"></audio>
I logged $listeners in music-player's mounted hook like this:
mounted () {
console.log(this.$listeners)
}
and the result was only an empty object without a timeupdate property.
However if I remove .native modifier from @timeupdate, I can see a timeupdate function in the $listeners.
I'm using Vue 2.5.16. Is this as expected? Why doesn't it work with .native modifier?
You should not use .native modifier here.
See https://vuejs.org/v2/api/#vm-listeners:
Contains parent-scope v-on event listeners (without .native modifiers).
@Justineo I don't quite get it. As explained in Binding Native Events to Components, this is just how you use .native to listen to inner elements. Then comes the doc stating you can't use .native here. Why?
Actually .native works as an escape hatch if you are using some third-party components which don't provide some specific events you need. Using it would make your code coupled with the implementation of those components. $listeners are used to decouple these parts so whether an event listener is .native should be transparent to the component user. That means you should only use v-on bindings without .native.
@Justineo I see. Btw since which version can I use $listeners?
@Justineo Thanks. I'm closing this issue.
Most helpful comment
You can use
$listenersto capture allv-onbindings of the component and selectively forward them to the native HTML element. See Binding Native Events to Components.