Skip to content
\n

The fun actually starts when you use this component.

\n

App.vue

\n
<callback-component @callback=\"async () => console.log('hello world')\" />
\n

As you can see, I can use the event listener syntax on the prop! And this won't give me any errors… in fact, it works like a charm. Why? I can also add @callback-called and @callback-failed listeners to react to the other emits.

\n

Can anyone send me a piece of the docs or explain this? I haven't found any references to this behavior.

","upvoteCount":2,"answerCount":1,"acceptedAnswer":{"@type":"Answer","text":"

The template attributes all get mapped down into VNode props (not to be confused with component props). The VNode props are the properties passed into the h() calls in a render function.

\n

For v-on (or equivalently @), it'll be mapped onto a VNode prop prefixed with on. e.g. @click becomes the VNode prop onClick. That part is documented at:

\n\n

There are a few other places in the docs that allude to this, but that's probably the most explicit. You can also see this using the Vue Playground to inspect the compiled output for a template with a listener.

\n

Inside the child component, any VNode prop can be turned into a component prop by listing it in props (or equivalent with defineProps). While it is more common for events to use emits (or equivalently defineEmits), it is also possible to use props for events. One use case for this is detecting whether an event listener is passed, which isn't possible when using emits.

\n

Another case where this is relevant is fallthrough attributes. VNode props that aren't listed in either props or emits end up in the $attrs. This includes event listeners passed in using v-on, which are copied from the VNode props to the $attrs with the on prefix. The $attrs needs to be compatible with v-bind=\"$attrs\", but that's fine because using v-bind with an onClick property works out the same as using @click. There is some acknowledgement of this at https://vuejs.org/guide/components/attrs.html#disabling-attribute-inheritance, which notes that 'A v-on event listener like @click will be exposed on the object as a function under $attrs.onClick'.

\n

While it isn't documentation, also note the warning message in this example:

\n\n

This warning acknowledges that an emitted event can either be declared in the usual way (using emits) or as an on prop.

","upvoteCount":2,"url":"https://github.com/orgs/vuejs/discussions/14107#discussioncomment-14995171"}}}
Discussion options

You must be logged in to vote

The template attributes all get mapped down into VNode props (not to be confused with component props). The VNode props are the properties passed into the h() calls in a render function.

For v-on (or equivalently @), it'll be mapped onto a VNode prop prefixed with on. e.g. @click becomes the VNode prop onClick. That part is documented at:

There are a few other places in the docs that allude to this, but that's probably the most explicit. You can also see this using the Vue Playground to inspect the compiled output for a template with a listener.

Inside the child component, any VNode prop can be turned into a component prop by list…

Replies: 1 comment 1 reply

Comment options

You must be logged in to vote
1 reply
@Serhansolo
Comment options

Answer selected by Serhansolo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants