I’ve created several components that communicate with each other using custom events.
The issue is that I’m having difficulties with event propagation. I have an App.vue component that instantiates a GeneriqueButton component, which in turn instantiates a BaseButton component. I’ve added an event listener on GeneriqueButton with the .stop modifier to prevent event propagation to App.vue, but the event still bubbles up to App.vue, I’ve message in my console.
I don’t understand why the event continues to propagate despite the use of the .stop modifier. I’ve verified that the event is emitted from BaseButton, but it’s still captured by App.vue.
Here’s the code for the three components:
App.vue :
<template>
<GeneriqueButton @base-button="printConsole"/>
</template>
<script setup>
import GeneriqueButton from './GeneriqueButton.vue'
function printConsole(event) {
console.log('App.vue : BaseButton clicked !', event)
}
</script>
GeneriqueButton.vue
<template>
<BaseButton @base-button.stop="printConsole" />
</template>
<script setup>
import BaseButton from './BaseButton.vue'
function printConsole(event) {
console.log('GeneriqueButton.vue : BaseButton clicked !', event)
}
</script>
BaseButton.vue
<template>
<button type="button" @click="$emit('base-button', $event)">
Click me
</button>
</template>
I use console.log in App.vue and GeneriqueButton.vue, each click on button I have 2 logs in my console:
.
Do you have any idea what might be causing this event propagation issue? Do you have any suggestions on how to fix it?
Thank you in advance for your help.
2
Answers
It looks weird, but it is actually not the custom event bubbling up, but the listener propagating down.
Here is what happens:
App.vue
sets an event listener on the GeneriqueButton button componentattr
object)attrs
are passed on to the root node, including the listenerNote that
.stop
will stop event propagation on native events, you could use it on the@click
on the button to stop the click event from bubbling. It does not work on custom events, which do not bubble at all.Here is what you can do to avoid the situation:
App.vue
, unless you explicitly want it to be passed to the nested single root elementAs per the documentation of Vue3.JS custom events not falls under default event bubbling like native events.
Unlike native DOM events, component-emitted events do not bubble. You can only listen to the events emitted by a direct child component. If there is a need to communicate between sibling or deeply nested components, use an external event bus or a global state management solution.