Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emitting events from components to router-view - bad code smell

I’m experimenting with Vue Router and I’ve got a bad smell coming out. Need to check with the community to see if I’m doing things right.

Prior to Vue Router I had a component as a parent receiving an event from its child and updating my main app data property:

<number-pad v-on:button-click="updateTotal($event)"></number-pad>

Don’t worry about the details but it was working.

When I move this into Vue Router it’s going to look something like this now...

const pageOne = {
    name: "page-one",
    template: `
    <div>
        <number-pad v-on:button-click="updateTotal($event)"></number-pad>
    </div>  `
};

...with the following in my HTML:

<router-view></router-view>

There’s a lot more I’m leaving out but you get the gist.

Anyway, this will render just fine and update the internals of the component, of course, but the directive isn’t going to communicate with the main data property any more unless I adjust some code to emit the data up one more level to the <router-view> component:

<router-view v-on:button-click="updateTotal($event)"></router-view>

It will now work (along with other code tweaks I'm not writing out for the sake of brevity).

In other words, when it comes to component relationships I went from a parent -> child relationship before Vue Router to a grandparent -> parent -> child relationship after.

Do I seriously have to duplicate all my bindings and directives to this new <router-view> grandparent in order to communicate to the main data property?

This smells very bad to me and is also a huge pain in the a**.

What can I do to make this situation better? Is the answer: Vuex! Or is the answer: no, you dope, you overlooked something simple.

Thanks.

like image 667
portnoy-the-elder Avatar asked Oct 27 '25 17:10

portnoy-the-elder


1 Answers

Vuex is one of the answers, but you can also define an event bus, i.e:

/src/event-bus.js

import Vue from 'vue'
export const EventBus = new Vue()

Import it in a component that's emitting:

import EventBus from '@/event-bus'

You would emit an event like this:

EventBus.$emit('button-click', payload)

Now import EventBus in a component that's receiving the event, and add a listener in your mounted hook:

mounted() {
  EventBus.$on('button-click', payload => {
    // handle event
  })
}

This works app-wide.

like image 167
dziraf Avatar answered Oct 29 '25 09:10

dziraf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!