Events vs callback props

In react, we would use callback props for parent-child communication. We could do that in vue, but vue also provides for communication via events. Is there a practical difference between the two, or is it just semantic?
One downside I see (and this caused me a few hours of lost work), is that events can’t be required, and listening for an event that isn’t being sent (let’s say it was misspelled) will fail silently.

2 Likes

You already found the one difference, apart from that, it’s only semantics.

About that one difference, it can be a pro and a con, of course. With callbacks, you have to check for the prop to contain a function before calling it, especially for optional ones, while you can just emit events without having to check for a listener.

I guess it depends on your personal preferences a bit.

Perhaps this is not your use case, but if what you want to do is updating a specific prop from the child component, you can have a look at sync modifier. That’s a “”“two-way binding”"" for props.

1 Like

Yeah, coming from React, I vastly prefer the prop function approach. It’s more explicit, and seems easier to debug.

I’m surprised there’s no official docs on the different approaches and their tradeoffs. Sounds like the standard way to communicate between components is via events. But I’m glad Vue at least provides us the option to take the React approach.

2 Likes

From a library/plugin perspective, I prefer events. It keeps the library lighter and let’s the consumer decide on usage.

1 Like

I can see your point. Hopefully libraries will keep all the events they emit well documented.

I do like the Vue devtools event logging. Thats a major advantage of using events at the moment.

2 Likes

That’s a great point there!

I’m in the process of converting an app to use typescript, and this is where explicitness really shines. In react, everything is a prop, and the prop structure is defined on the component (ie., interface Props {…}; … extends Component), once you do that typescript can 1) make sure, at compile time, that you’re passing in the correct props, correctly, 2) make sure your props don’t get into a state that is against your business rules (yes typescript’s type system is powerful enough to do that). That includes things like making sure your component only takes one prop (a single child) or a single function (function as a child), which are things that can only be enforced in vue by convention.

Now, assuming that at some point vue-language-server will be able to support something similar in templates (it can work now with JSX with a little hack), that would only work for props. Since events, or slots are implicit, that can never be type checked. I’ve been tripped up multiple times because I’ve misspelled an event. Also, while new things like .sync can be great to save boilerplate, this stuff has to all be documented well by libraries (since again those are just events)

The event logging in vue is definitely nice, although it can also be replaced by your favorite state management system.

1 Like

I’ve found that 75% of my event are replaced by state management, but there are still UI use cases where events are appropriate. One cool pattern for global UI events I’ve seen/used is to bounce events up to the component root. One important caveat is to build in listener removal on UI components that do this because Vue only cleans up event on the instance, not the events attached to other instances (I.e. The root)

I also wanted to add that, forgetting typescript and state management, props can at least be caught at run time. A misspelled event will never get caught and leave you scratching for what went wrong. Perhaps it would help if events also could be declared.

I like using a dictionary or module of event constants, but that doesn’t work in templates. Still, what’s different with that and saying document.addEventListener('misspelledevent', callback)?

I’m talking about props vs events…not events vs dom events. Although, as you yourself mentioned, document.addEventListener('misspelledevent' has the advantage that it is real code, and you can things like constants. That’s a small side point as I would rather jump in a lake then use that model of programming.

I don’t think events should be in vue. There should only be props. The problem I see with events is you’re given the initial impression that they are events, like dom events! but no, they’re just callbacks with no bubbling behavior or anything really similar to events at all. There’s not even a place to declare which events a component emits - you’re left grepping to find which events you can listen in on. Props are declarative, can be defaulted, required, validated, etc.

1 Like