Is there a way to allow events to bubble up when using a component within a component?
My application is a dynamic menu. The dynamic menu is a component (dyn-menu
) and it uses a local component (menu-item
) for each of the <li>
elements. Each <menu-item>
has a click handler associated with it that emits a custom event (with an ID for menu item in the full implementation). But the application doesn't see the events issued by <menu-item>
because they are not bubbled up.
Is there a way to allow the <menu-item>
component, which is local to the <dyn-menu>
component, emit the event and still allow vapp
to see and handle the event?
I'm pretty new to Vuejs so I might be missing something obvious. And it's possible that I'm trying to solve this by using two components and that's not the best way to handle it. Is there is a better way to approach it?
Here's a jsfiddle. You have to remove the @dyn-menu-item-click='itemClick'
line in the <dyn-menu>
template to illustrate that the event doesn't bubble up if the component doesn't handle the event. If that line is removed then <dyn-menu>
doesn't handle the event but vapp
never sees the event either.
As of Vue 2.4, components can access their parent's listeners through the
$listeners
property. You can set a component to pass through its parent's listeners to particular children by adding an attributev-on="$listeners"
to the tags for those child elements. See the docs at https://vuejs.org/v2/api/#vm-listeners.You can also forward specific events with an attribute like:
@dyn-menu-item-click=$listeners['dyn-menu-item-click']
.It's still not true bubbling, but a less verbose way to re-emit events.
There are 4 options I know of
this.$parent
(repetitively) on the child component to access the desired parent and emit the event. (see "Implement your own bubbling event plugin" below)provide
d by the parent andinject
ed in the children.Implement your own bubbling event plugin
It's very simple. The plugin adds a new
$bubble
method that emits events that bubble to their parents. I considered publishing a plugin that does this, but it's so simple that the overhead is not worth it.Event bus
The event bus looks like this:
Working example: https://jsfiddle.net/7vwfx52b/
There are plenty of event bus plugins listed here: https://github.com/vuejs/awesome-vue#custom-events