2

I'm new to Vue and there are some things I didn't understand yet.

enter image description here

In the first child there's a click event to $emit information to the next child. But in the other one, the second child, is there anyway to pass the information to the next child using $emit without a click event or any other event (like scroll, hover etc)? I just want to pass it ahead. Can I use mounted()?

Kali
  • 561
  • 1
  • 8
  • 22
  • Related: [VueJs 2.0 emit event from grand child to his grand parent component](https://stackoverflow.com/questions/42615445/vuejs-2-0-emit-event-from-grand-child-to-his-grand-parent-component) – zcoop98 May 18 '21 at 13:51

1 Answers1

2

Yes! What you're looking for is $emit(), in combination with the v-on directive, both of which it sounds like you're already using.

In the child component that you mention, the lowest one on the chain, you're already capturing a click event from some component, and then presumably using $emit('my-event', [...some data...]) to emit a new event out from the child component itself.

All you need to do now is to add event listeners and handlers in the components up the chain, using Vue's custom events mechanic, so that they can receive and emit their own events, and the data can make it up to the parent. Custom events allow your components to emit and listen for events of any name, which may carry any data they'd like (this means they're not limited to being click/ hover/ blur/ etc.).

Here's the step-by-step of that approach:

(Structure: Parent <--> Child #1 <--> Child #2 <--> Child #3)

  1. Child #3 captures a click event, and emits an event in its handler
  2. Child #2 is listening for this event on #3, captures it, and $emits its own event in its handler
  3. Child #1 is listening for this event on #2, captures it, and emits own event in its handler
  4. Parent captures event, and executes handler

In code, you'll have a listener and handler in each of your components, which can look something like this:
(I've used inline handlers here for brevity, but you can use defined methods as handlers too, just call this.$emit(...) from the method.)

Child #3:

<component ... @click="$emit('my-event-a', $event)" />

Child #2:

<ChildComponent3 ... @my-event-a="$emit('my-event-b', $event)" />

Child #1:

<ChildComponent2 ... @my-event-b="$emit('my-event-c', $event)" />

Parent:

<ChildComponent1 ... @my-event-c="myHandler" />

$event here is just special Vue syntax for referencing the event data in an inline handler, which in this case allows your new event to contain the same data.

The events in the various child components can be named whatever you'd like, just make sure that the respective listeners are listening for the correct event name (eg. @event-x="..." for $emit('event-x') and @pizza-eaten="..." for $emit('pizza-eaten')).

I also wanted to mention that passing the event object (or any data at all) with an emitted event is completely optional. To do so, just invoke $emit with the event name and no other arguments: $emit('my-event'). This is useful when you simply care that an event has occurred, and the handler requires no further info.


There are many ways to approach this problem, but this is the most straightforward to understand, and works great as long as you don't need tons of direct interaction between a component and its deeply nested children.

If you do find your component structure getting more complicated, then you may want to look into a fully realized state management solution, like Vuex, which allows your components to interact with a state manager rather than having to deal with tons of events through a complicated component structure.

tony19
  • 125,647
  • 18
  • 229
  • 307
zcoop98
  • 2,590
  • 1
  • 18
  • 31