Vue 3 Fundamentals

script setup

Ben Hong

Ben Hong

Vue 3 Fundamentals

Check out a free preview of the full Vue 3 Fundamentals course

The "script setup" 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 a Vue compiler option to fully buy into using composition API while saving code space. Student questions regarding if this route would result in more concise components and how stable the script setup is are also covered in this segment.


Transcript from the "script setup" Lesson

>> So we're on to our next section regarding Composition API with script setup. All right, so let's context that a bit here. When we take a look at this user page, you'll notice that, well, most of our component is actually in Composition API, minus the component registration right here, everything else is Composition API.

And so Vue is certainly, when we were thinking about the developer experience of working with Composition API, it was a bit like, well, okay, this is cool, right? We can break stuff up, we can go ahead and write our JavaScript in a way that's kind of more natural for us, we can group it the way we want.

But then the fact that we have to constantly write our returns gets a little bit tedious. Especially when you have a lot of things to return, that's not something you have to manage in two different places, right? You have to define what you're gonna do, then you're gonna return it.

Couldn't Vue be a little bit smarter about this somehow? And so this is where things like build tools are really great. Because with Vue 3.2, we introduced a compiler optimization, where it allows us to actually fully buy into the Composition API while saving us some code space. And more importantly, allowing us to be more succinct and concise.

And so let me show you what I mean by that. So let me go ahead and go over to the playground, and let's go into the pokedex. All right, so the pokedex, similar to what we had earlier, is basically mostly bought into the Composition API. In fact, there's only a couple of things we need to do to fully change it.

And so for now, let's see, computed, in fact, this was a made up thing. So we're gonna go ahead and delete computed from here cuz we don't need this regionNameLowerCase. And then methods changeRegionName, again, was something we decided to do just to sort of change things. So we'll go ahead and migrate that, cuz what are methods?

Methods are JavaScript functions. So const changeRegionName = function, where we say regionName. And regionName in this particular case is a ref, which means we need to unpack it, and it's going to be Hoenn. Once we have that, we can return that to our template. And then there we go.

And then we don't need to log any of this. So now, we should be back in a similar state to what we had earlier when we had the user page. Okay, so let me go ahead and actually checkout branch 11-begin. There we go. And then we'll check out branch 11-exercise, and let's commit this change real quick.

Feature update pokedex to be almost fully composition api. Okay, so what is script setup? Well, script setup is exactly as it sounds, in that what you do is you add an attribute to your script block called setup. And what that does is it tells you this entire block is going to be Composition API.

No options will exist in here. So what does that mean? Well, first thing first, there's no more object, cuz that's what options API is all about, about defining this object. So export default disappears, Then we can save that. But that's still gonna break, which is totally fine, cuz you know why?

We already know that it's in setup, so the line 5, this async setup here, also not necessary, Delete > Save. Better, but here's the other thing. Because we're now in a compiler optimization, meaning Vue can now do a lot more static analysis and those sort of things, we don't even need to return anything either.

And believe it or not, this block of code here, in fact, let me just delete the console.logs here, this whole thing just works.
>> You just sold me.
>> [LAUGH]
>> I was super skeptical until this moment.
>> Yeah, this is the mic drop moment for those who are thinking about Composition API.

This makes a lot of people excited, especially for those users who are heavy on the JavaScript side. Or more importantly, if you're even thinking about TypeScript, Composition API works with TypeScript naturally. In terms of annotating types and all that stuff, we don't have time to talk about that today.

But there's a Vue 3 and TypeScript workshop that just actually released recently. So if you wanna check that out to learn more about how that might work together, you can totally check that out. But there you go, this is how you get a component to fully opt into Composition API while not having to worry about any of the.

One of the things actually that you might be thinking about is that we had an async earlier, right, on our setup. But when you're in the script setup, basically, Vue hoists and does all the async stuff for you so that you don't have to manually assign it here.

It'll automatically detect the async stuff, and do what it needs to do. And so just like that, we've now have a component that's fully opted into Composition API, no options anywhere. The only thing I will add is because this probably wouldn't be the most intuitive, is that let's say we wanted to add our BaseButton inside of this layout.

All we do is you do BaseButton, we import it, let me do this, BaseButton. And believe it or not, just by importing it, you've already registered it. So I can come down in here now and just go BaseButton, like that. You can see, there's our BaseButton. So, a little bit of show and tell, does anyone have any questions about what they've seen so far?

>> I have to imagine that in practice, this really forces you to make concise components because it's gonna be a mess if your component-
>> [LAUGH] And you bring up an excellent point. So as we can see here, right now, the code is fairly short, easy to follow, but you can imagine, it's very easy for a team to get carried away with this.

And spaghetti code can become very problematic very quickly. Again, one of the things I wanna emphasize is that there are trade offs when you go the options route versus the Composition API route. And understanding those trade offs are, if we think about it, are what make us experienced as engineers.

And so knowing that, you just have to realize that Composition API means there's flexibility and freedom. And so your team has to then design the conventions its going to use in order to make sure that your code is still maintainable and readable. As much as options API was a little bit rigid as far as telling you where to put stuff, it didn't mean everyone knew where everything was at any point.

And anyone could basically jump in, but here, this is just the beginning. Because what we're gonna do next, after you all practice doing this yourselves, is we're gonna talk about how you can extract these into modules that can then be explicitly tossed around different components. There is one more thing I need to cover before we cover the exercise.

We've done all this stuff regarding doing functionality, data computed, and we've talked about components. We did not talk about props, we did not talk about emits. So remember if we look at our UserCard that I had earlier, we see that, and the options is very easy, you just have the props, you have your emits, you just define it as you see fit.

It's actually not that much harder when it comes to Composition API, it's just, what do you think you need? You need a helper function. And so they are aptly named, defineProps and they are defineEmits. These are the two helper methods that you need to know about. And so the way it works is basically, if this pokedex wanted to say, take a region of props, sorry, a region of Kanto, for example, of which region it was looking for.

You would say, defineProps is a function that takes an object, where we then can say the region is going to be of type String, and I can say that the default is going to be Kanto, for example. As you can see, the syntax is actually very similar to what we learned already.

The main difference being that one is being called by a function. But the second part, which is actually really important, is that if you want to actually use the prop in your computation. Say for instance, inside of this computed, right, we want it to actually say, we want it to be uppercase, and we wanna add the prop to it too.

How do we do that? Well, defineProps as it stands right here is just a function that's being initiated. Well, we need to do then, cuz it's vanilla JavaScript, is say, const props. Or to be honest, you can name it whatever you want, it's JavaScript, but I would recommend just naming it props, because then you can say, props.region.

And then when you do that, we can see at least, it looks like the default is giving me some problems, so I'm gonna ignore that for now. But we can see here, if I go to App.vue, where is, wrong App.vue, App.vue in the playground. Give it a region, let it switch it off to Hoenn this time, there we go.

I need to figure out what the default things later, but at the bare minimum, you can see that's how you define props. And then similarly, if you're doing emit, you basically const emits, define the emit. And then here, same thing, we can say, change-region, for example. And then everything still works exactly as we learned in this workshop.

>> How in flux is this API?
>> defineProps and defineEmits is-
>> I mean, the whole section you showed.
>> Got it. Okay, so the question here is around how stable the scripts setup is? It's fully stable at this point, production ready ever since 3.2, so that's the big caveat here.

If you're using anything less than Vue 3.2, you won't have scripts setup, the compiler optimizations aren't there. But going forward, honestly, I have seen a lot of code bases, a lot of people just opt into this fully from the get go. So yeah, consider it staple on that end.

For things like defineProps, defineEmits, they're still playing around a little bit sometimes with how they can optimize the DX of, as you saw, default was acting a little bit funky. I have to look into that why, but those are things that are still kind of being refined. But if you can be guaranteed of anything, it's that Vue tried to do its best to be progressive about how it makes these changes.

So that as long as it's not marked as experimental, you can count on your stuff working in production. And then sure, we might introduce another syntax that would make it even easier for you just like we saw with script setup. Because we got feedback on Composition API, right?

People liked it, kind of verbose, people had their feelings about it. And when we saw, I think, inspired by things, Svelte was doing with compiler optimizations, we said, why not? These are things that we can also do for our users. And so script setup, I believe, don't quote me on this, but I believe was also inspired from what we saw with Svelte.

Cool, so actually, we're not calling emits right now, so I'm just gonna, actually, I can just make another example for people right in here. We could say, emits, what does it emit? It emits the change-region. That's your example right there. Okay, cool.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now