The naive way to do it…
Child component (event bubbled from)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <!-- ChildComponent.vue --> <template> <button @click= "handleClick" >Click Me!</button> </template> <script setup> import { defineEmits } from 'vue' const emits = defineEmits([ 'clicked' ]) function handleClick() { emits( 'clicked' , 'Some data' ) } </script> |
Intermediate component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!-- IntermediateComponent.vue --> <template> <ChildComponent @clicked= "handleClicked" /> </template> <script setup> import ChildComponent from './ChildComponent.vue' import { defineEmits } from 'vue' const emits = defineEmits([ 'clicked' ]) function handleClicked(data) { // Bubble up the event to the parent of the WrapperComponent emits( 'clicked' , data) } </script> |
Parent component
1 2 3 4 5 6 7 8 9 10 11 12 | <!-- ParentComponent.vue --> <template> <div> <IntermediateComponent @clicked= "onChildClicked" /> </div> </template> <script setup> function onChildClicked(data) { console.log( 'Event data from child:' , data) } </script> |
The more straightforward way to do it
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!-- IntermediateComponent.vue --> <template> <ChildComponent v-bind= "$attrs" @update:modelValue= "handleModelUpdate" /> </template> <script setup> import ChildComponent from './ChildComponent.vue' import { defineEmits } from 'vue' // Emit function that captures all event names const emits = defineEmits() function handleModelUpdate(value) { emits( 'update:modelValue' , value) } </script> |