Hey.
Currently we have the $emit
method to fire an event in the VM itself, $dispatch
method to fire an event up the parent chain and the $broadcast
method to fire an event down the children chain.
Many times I find myself having a "manager" like instance which has multiple children and when one children changes it should notify its siblings for that. Imagine we have component A
, B
, and C
where A
is the "manager" and B
and C
are its children. Now if C
changes, I would like to let B
know of that and maybe do something with that. Currently I do this in a tricky way:
// run this in `C` component
this.$parent.$broadcast('MyEvent', data)
Now B
will indeed get the message that something happened with its sibling.
I was wondering if maybe we can create a native method for that since it seems to be a common task? It can be just a wrapper method for this.$parent.$broadcast
.
Also, currently we can't fire an event globally that ANY vue instance that is "alive" can listen for. If we want to do so we need to trigger all of the events method:
this.$emit('EventOccured', data)
this.$broadcast('EventOccured', data)
this.$dispatch('EventOccured', data)
Maybe we can add some method to handle this as-well? I honestly haven't had any occurrence where I had to do so but it seems like something that should be there.
There are other ways to do it, in case you interested: Flux model (I have used Vuex); Third-party event emitter; props
.
Often, as Evan says, event-approach is little hard to reason about, compared to props for example. I would personally go with Flux (maybe try Redux) to share store (data) and actions (functions) between instances.
@azamat-sharapov I don't think we need to delegate that job to a 3rd party package as it feels like it needs to be something that Vue provides. It's not rare at all where you want to notify your siblings for something that happened and they may do something as a result. That's true that I can fire an event using jQuery or some other library or native js and listen to that event in my Vue components but that just doesn't feel right.
Vue is not an all-encompassing framework. It doesn't attempt to solve all
your problems and you should not limit yourself to a Vue-only solution.
On Mon, Nov 9, 2015 at 12:27 AM kfirba [email protected] wrote:
@azamat-sharapov https://github.com/azamat-sharapov I don't think we
need to delegate that job to a 3rd party package as it feels like it needs
to be something that Vue provides. It's not rare at all where you want to
notify your siblings for something that happened and they may do something
as a result. That's true that I can fire an event using jQuery or some
other library or native js and listen to that event in my Vue components
but that just doesn't feel right.—
Reply to this email directly or view it on GitHub
https://github.com/vuejs/vue/issues/1768#issuecomment-154934823.
@yyx990803 that's for sure. I never mentioned that I try to use Vue for everything, I just think that that it's an elementary task that is pretty common and maybe should be addressed as it's seems to be easy to implement and it isn't presenting anything new but just a nice addition to the current events system. It's like the polishing the current events system. Whether to do it or not is entirely up to your decision. That was a mere suggestion.
My opinion is that when you need this type of event communication, you should use a global event bus instead. And that's probably simpler than you think. If you are using Webpack or Browserify, they already shim Node's event emitter for you, so you can just:
// event-bus.js
module.exports = new require('events').EventEmitter()
This requires nothing from Vue itself. It's just a pattern that can be applied in any application.
I'll just leave this here as someone might be interested in a simple solution with Vue itself.
Register a global Vue instance very early in your application just to act like an event bus:
window.eventBus = new Vue();
When you want to emit an event, do this:
window.eventBus.$emit('your-event-name', data);
Then, wherever you want to listen to events, register this listener:
window.eventBus.$on('your-event-name', function(data) { doSomething() });
@aledmb FYI it's already in https://github.com/vuejs/vue/issues/2873, Upgrade Tips
-> How to Deal with Deprecation of $dispatch and $broadcast?
:smile:
oh that's so nice to see!
bus pattern works well, thanks aledmd
@aledmb your solution was fantastic! solved a problem of mine!
import EventEmitter from 'events';
export default class VueMitter extends EventEmitter {
constructor() {
super();
this.$emit = this.emit.bind(this);
this.$on = this.on.bind(this);
}
}
//in main
Vue.prototype.$eventHub = window?window.mitter?window.mitter:window.mitter= new VueMitter():new VueMitter();
Most helpful comment
I'll just leave this here as someone might be interested in a simple solution with Vue itself.
Register a global Vue instance very early in your application just to act like an event bus:
window.eventBus = new Vue();
When you want to emit an event, do this:
window.eventBus.$emit('your-event-name', data);
Then, wherever you want to listen to events, register this listener:
window.eventBus.$on('your-event-name', function(data) { doSomething() });