Check out a free preview of the full Vue 3 Fundamentals course
The "Emitting Custom Events" Lesson is part of the full, Vue 3 Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:
Ben discusses defining and emitting custom events, defining global methods, and demonstrates the Vue dev tools timeline registering DOM events. Student questions regarding if events traveling multiple levels have to be caught and reemitted and if there is an emit equivalent in Vue 2.
Transcript from the "Emitting Custom Events" Lesson
[00:00:00]
>> We've danced around this topic a lot at this point and I'd love to address this. So as a recap on the context of what we're talking about is, at this point we're talking about children components, trying to figure out how the heck to update the parent component.
[00:00:12]
Because we've talked about the fact that well, we don't wanna mutate props, as we can see very clearly here, we're being yelled at, don't mutate props. On the other hand, we talked about passing functions down as in like, if there was a method on this component that was called change name, and call it this data.user.
[00:00:32]
Data.name equals or say this is like an argument for new name and then just like that, right. And so then you'll be like, okay, well inside of user, I'm gonna pass this method called changeName. And then it'll take on the reference to that method and then we have this changeName, which is a function.
[00:00:53]
And then it's let's say required true and then let's say we have a button here that's like hey like changeName. That's like most people's instinctual way and how a lot of frameworks approach this problem. Because the parent is telling it what to change and the child obediently does it.
[00:01:13]
The thing about this mental model though is that it forgoes the fact that actually if we think about how the web is designed, when we have child DOM elements, what do we have do? We have it bubble up events, that's actually how the web is built natively if we think about it.
[00:01:29]
It's not actually the parent is telling it what to do it's saying, when that a button that a child has happened, it bubbles up that event, that's where we get these concepts, right. That a click has happened therefore, how does this relate to the chain of communication? And so what we're gonna talk about right now basically at this point is how we can basically emit custom events from our child, to tell the parent that something is happening.
[00:01:51]
So let's actually go ahead and just take this user card example, why not, why wouldn't we? So let's go ahead and just set this context up a bit so let me just remove this. And how we would do this, actually I think I might be able to leave that.
[00:02:09]
For now let's do this, change name, okay. So let's make sure everything's at least rendering correctly on our side for the app, okay. So let's start with something simple, which is that if we click a button from the child, it will basically tell the parent that hey, I want to change the name.
[00:02:30]
And that when that happens, what we want it to do is this is updated directly to Charlie. So we won't even worry about arguments right now. And so again right here just to show that this works if we add the click, and we add change name, change now.
[00:02:46]
You'll see Ben does switch to Charlie as expected, okay. As expected, but this method is existing all the way up here. So how the heck does a user card get access to that, without you passing the prop down as a function? Well, the way we do that is with this concept, it's new to Vue 3, did not exist the Vue 2 call it emits.
[00:03:11]
An emit is the equivalent of props, props is saying hey, this is what I'm expecting to send down. Emits is our way of documenting, hey, this is what I'm gonna send up. So if you think about it, this is actually following the one way data chain of unidirectional data flow, because, the data comes down.
[00:03:27]
And then you're basically sending a signal up to say, hey, I want something to change. And then the basically the parent knows change it then send that change back down. So in that regard, it follows that traditional web model. And so to show you what that means, we'll say emits so again, emit the event change name, all right.
[00:03:47]
And so the key thing with the emits is to think of this as custom events, right? We're used to click, key up, those are things that are events that already defined for us. This is a custom event that we're emitting, okay? And so, what we get to do then, is once we have our emits defined, we get to do is we get to call a global method called emit dollar sign emit.
[00:04:08]
And so if this is your first time using Vue, despite you're probably wondering, what is this dollar sign here? It's basically views way of name scoping is a global function that is available to view specifically. So now that you know this is not just something in JavaScript, this is a view thing.
[00:04:22]
We're gonna emit what, we're gonna emit change name, okay. And this is now where the dev tools become very handy. Instead of the dev tools there is this tab right here called a timeline. And what it allows you to do is actually notice when different events are happening so you notice that if I just click on the page here, it actually does gives me a timeline of snapshot of what's happening.
[00:04:48]
It even actually has the coordinates on here I am noticing. And so you see, it actually tells you the actual position of what's happening, and so when it comes to debugging, this is pretty darn useful. And so you notice here though, if I click changeName, something happens here.
[00:05:02]
So let me scroll over, I think it's losing the scroll, okay, it's right over here. I think I zoomed out too much. Refresh, there we go. Where is my sidebar view reload component's timeline, I hit it, here we go. My gosh, and I was like, where did it go, okay, click change name and we'll see a couple things here.
[00:05:36]
One, you see right here, change name event has been emitted, and so it's been emitted by user card. And so you also know that it happened with a click as well, because you'll see that here, it has the mouse up mouse down the click event. And then here is where we get that change name event.
[00:05:54]
And you notice here, it actually tells you a little bit more about the event info that, is from the component user card the event is changing. But also, we haven't gotten to this yet, we can actually pass parameters up. Because sometimes you're gonna be customizing stuff at the child level, but you need to say, here's some of the customizations I'm sending up to the parent and this is what I'm gonna send.
[00:06:11]
And so when you do this, what happens is. On your component, we get the ability to listen to.what? Listen to our custom event which is what, change name. So this is no different than our at click, at key up. So I'm actually go ahead and delete at, because that's my prefered and then from here what are we gonna do when this is called, we're gonna run the method change name.
[00:06:38]
Okay, there we go. NPM run dev. There we go, yeah I figured. So, this takes some getting used to because I know that again, this is not traditionally how people are thinking of things. But It's funny when we think about the primitives were given when building with the web.
[00:06:57]
Event bubbling is a very standard way of building with things and more importantly I think, it allows for I'll call it like a cleaner way of removing that. He's sort of strict instructions that you're passing down from the parent when you just pass the function. Because now all of a sudden that function, I've just seen in code bases, when people do that it just gets hairy in terms of like people, then they start passing in the wrong function.
[00:07:22]
Cz then you have to make sure the function is doing what you want it to in the child, which means you actually now have to check the parent, to make sure that it kind of makes sense. Whereas like when you just emit an event this child component will use in a lot of different contexts.
[00:07:35]
And then the parent can do whatever it wants with it and it makes sense because you're saying, when the child component has this custom event, I'm gonna run this function which lives in this file. And so in that regard, it really does help to really encapsulate that single file component mentality.
[00:07:48]
We're also building on web standards and principles, that we're actually using on a day to day but often overlooked, yeah.
>> If you were to bubble up multiple levels, would you have to catch it, emit, remit it?
>> Yep.
>> You can't just say, emits, emits, emits, emits the whole way up.
[00:08:04]
>> You cannot, and so that's a great question, so let me read it. So the question here is that right now we just have a single parent single child, one omit whatever. What happens when you have like a great great great grandchild wanting to communicate info up. And so, emits and props really are designed for a closer relationship like when you're closer together.
[00:08:26]
This prompt actually had that same problem. And so the pattern that actually the anti pattern that resulted from that is called prop drilling, and so you have app to view has this global thing and then you joe joe joe joe, pro pro pro and like none of the components use it until like this one.
[00:08:39]
But then the problem with prop drilling is that the moment you remove one in the middle, the whole thing just falls apart immediately. The answer to this is basically using composable and state management in a way that is. At that point I would argue, If you have data that is shared across components at that depth, it probably makes sense for it to be encapsulated in a module that can just be shared across both files.
[00:09:00]
The props is really in my mind design when there's a tight coupling between the two components, and you want it to behave a certain way. Otherwise, what we'll see here later on is around, other flexible APIs that allow it to do more than just sort of these sort of rigid instructions between components.
[00:09:17]
Does that help to answer your question?
>> Is there an emit equivalent in Vue 2?
>> Okay, so good question, in regards to Vue 2, the $ sign emit actually does exist as a function. So, it's not that your custom events are not new to Vue 3. What is new to Vue 3 is the fact that you can basically document them inside of your options.
[00:09:39]
Because the problem, then this was a misstep on I guess on our part we didn't think about it. Is that when you don't have this emits property, it seems like a small thing, but if you start emitting multiple events, it starts getting really hurried to track in a big component of like, wait, what events are happening?
[00:09:55]
Where is it, I mean, that's why we have prop definitions too, actually it's to let, hey, what am I expecting to receive? The emit does the opposite for us where what kind of events are you expecting to emit so that people don't just randomly create their own. And so to be clear, and just to kind of wrap that up.
[00:10:10]
If you don't like emitting directly here, we can actually just do something like tellParentChangeName. And this can just be a method, tellParentChangeName, and we can do this dot dollar sign emit, this will be the same exact thing. It's up to you whether you wanna call it here or you just wanna call it inline.
[00:10:32]
Once again, I think that's more of a stylistic thing. Cuz some people would be like, well, if it's just this one event and I'm not tracking that much, I'm just gonna inline it.B ecause it's not really being reused. On the other hand, if you have this being called a bunch of places, you might not really wanna define that everywhere, you might wanna change it in one place.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops