The fun actually starts when you use this component.
\nApp.vue
<callback-component @callback=\"async () => console.log('hello world')\" />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.
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.
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.
\nInside 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.
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'.
While it isn't documentation, also note the warning message in this example:
\n- \n
- Playground \n
This warning acknowledges that an emitted event can either be declared in the usual way (using emits) or as an on prop.
Why does this work? (event-listner prop) #14107
-
|
Hi I am confused over here, I made a modal component that I can feed with function props. These can even be validated using runtime validation (as stated here). It feels like an anti-pattern as soon as you use a prop name called "onXxx" in this example, I used
<template>
<div>
<button @click.self="runCallstack">Callback button</button>
<p v-if="props.onCallback">Callback function detected</p>
<p>
{{ callbackCalled }}
</p>
</div>
</template>
<script setup lang="ts">
import { ref } from "process";
import { withDefaults } from "vue";
interface ComponentProps {
onCallback?: () => Promise<void>;
}
const props = withDefaults(defineProps<ComponentProps>(), {
onCallback: undefined,
});
const callbackCalled = ref(false);
const emit = defineEmits(["callbackCalled", "callbackFailed"]);
async function runCallstack() {
try {
// Do some pre work
if (props.onCallback) await props.onCallback();
// Do some post work
} catch {
// maybe do a catch or something and emit that
emit("callbackFailed");
} finally {
// when done with it all emit that
emit("callbackCalled");
}
}
</script>The fun actually starts when you use this component.
<callback-component @callback="async () => console.log('hello world')" />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 Can anyone send me a piece of the docs or explain this? I haven't found any references to this behavior. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
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 For 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 listing it in Another case where this is relevant is fallthrough attributes. VNode props that aren't listed in either While it isn't documentation, also note the warning message in this example: This warning acknowledges that an emitted event can either be declared in the usual way (using |
Beta Was this translation helpful? Give feedback.
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 withon. e.g.@clickbecomes the VNode proponClick. 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…