should vuejs2.0 keep the $broadcast, $dispatch event api? No good solution to address point to point parent-child communication in 2.0
See original GitHub issue@yyx990803 , Hi, vuejs core team, I am struggling on find a good solution for point to point communication between parent child components with vuejs2.0. Because vuejs2.0 has deprecated the $broadcast,$dispatch api, it is very hard for me to find an alternative solution $broadcast,$dispatch provides with vuejs2.0 event bus feature. I have written a thread in the forum about this topic here, and I’d like to paste it here for more discussion.
PLEASE DO NOT CLOSE IT UNLESS have a good idea or solution on vuejs2.0. Thanks~!
<pcom id=1>
<soncoma></soncoma>
<soncomb></soncomb>
</pcom>
<pcom id=2>
<soncoma></soncoma>
<soncomb></soncomb>
</pcom>
In above code, when child of pcom1, for example, soncoma $emit a event, say,
bus.$emit('son-coma-event',somedata)
on the pcom, we listen that event with
bus.$on('son-coma-event',function(){})
I only want pcom1 will handle that event, but unfortunately pcom2 will also handle that. How to tackle this condition?
One of the workaround in my application is to use the this.$parent as event bus In child:
this.$parent.$emit('some-event',someData)
In parent:
{
created(){
this.$on('some-event',function(){})
}
The negative point for above workaround is:
- we couple a lot on the parent-child relation;
- it does not work if there is more in-depth level of parent-child levels;
In some more complex conditions, it will be more difficult to find a good solution for the custom event system, for example, a recursive component
<pcom>
<recursivechild>
<recursivechild>
<recursivechild>
</recursivechild>
</recursivechild>
<recursivechild>
</pcom>
<pcom>
<recursivechild>
<recursivechild>
<recursivechild>
</recursivechild>
</recursivechild>
<recursivechild>
</pcom>
how recursivechild communicate to its direct pcom component? Please give your idea or point on these topics. Thanks~!
Issue Analytics
- State:
- Created 7 years ago
- Comments:41 (21 by maintainers)
Top GitHub Comments
Copy/pasting my own comment from another issue: https://github.com/vuejs/vue/issues/2760#issuecomment-250883407
I think removing $dispatch was a terrible idea. This wasn’t the first ui framework/library to implement the notion of bubbling actions/events up a visual tree. It’s a well established idea. Why take away this functionality on the premise that " being able to dispatch a event that causes side effects in its unknown parent tree sounds like a recipe for trouble to me"? You need to leave this responsibility to the users. I’m sure most have the common sense to use this feature appropriately. It is not a new concept!
I really can’t see the benefit of this change when this library is built upon long time established web technologies/concepts such as the DOM and DOM events that do in fact bubble up the visual tree and have been doing so for years with no one complaining. Isn’t the idea of components something that has been recently embraced thanks to the W3C proposal for web components? In my opinion, It only makes sense that Vue components behave similarly to regular DOM elements in regards to how event handling is done.
The proposed alternative to use a global event bus seems illogical to me when something more practical, effective, and easier to understand (due to it being a well established concept for years) already existed.
Other proposals in this thread remind me of how EmberJS wants to do it. Passing closure actions as properties to the components down each level of the hierarchy. So tedious and unnecessary! Vuejs was the reason i wrote https://www.npmjs.com/package/ember-component-action-bubbling!
Aside from this, I really like your library. But seriously, I think this was a terrible change.
@rhyek I would like to give my 2ct about a couple of points you raised. Since the discussion has already brushed a number of topics, I would like to get back to the basics about why we deprecated $diospatch and $broacast:
1. implicit coupling.
If you have a parent and a deeply nested child that dispatches an event, there’s no way to infer this relationship from the code (and the same is true for
$broadcast
, oviously.)If you look at the other changes and deprecations we introduced with Vue 2.0, you might realize that removing implicit behaviour in favour of explicit alternatives is a common theme, and deprecating
$dispatch
fits right in there.Example:
This is fine when the parent only has one direct child - but in that case,
$emit()
with a listener in the template is no real extra work, either.It becomes hard to follow (especially in teams) as soon as you have nested children (especially deeply nested), or even more than one direct child - you either have to look through all children, or rely on code comments to document which event is tiggered from which child component - which is additional boilerplate, as well.
You say that you like $dispatch and $broadcast because you don’t have to pass them through other components. And I can agree that it’s easier - but we have not come across many situations where this was actually nessessary, or rather: if there was such a chain of passing up an event, it would rather be the case that the data would be changed/appended/ during this trip by component in between.
2. Event names
when you use
$dispatch
with deeply nested components, you would have to be very explicit in namespacing your events, because otherwise, they could be clashing:…and if those children are third-party-libs, your screwed now. or have to catch the event in some component in the middle just to rename it before you
$dispatch()
further up to the parent. And don’t forget to comment this, because someone looking at this code might think why you do nothing other with an event than renaming it.Using $emit and template listeners does not have this problem. you can use simple, short event names everywhere, they won’t clash as each event has it’s own callback attached in the template
@close="callback
".If we thought both paradigms can work equally well, we would treat them equally. But we don’t think that, for the above reasons and more.
Therefore, we try to steer users to the pactices we found to work best, while leaving a way to get around it with the “global Bus” method.
I would also like to talk about your worries about global state, but am not sure I understand your position fully yet.
Maybe you can provide an example where you think $dispatch and $broadcast work best for you, and I try to show you how “our” approach could improve the situation?