Check out a free preview of the full Nuxt 3 Fundamentals course
The "Options API Exercise" Lesson is part of the full, Nuxt 3 Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:
Students are instructed to create a photo gallery component that returns a list of photos from a remote API when a button is clicked. To begin the exercise, check out the 01-exercise branch. The solution can be found on the 01-finish branch.
Transcript from the "Options API Exercise" Lesson
[00:00:00]
>> So this is the basics of options API. And so just to get people practicing with it a little bit, what we're gonna do for this exercise is you're gonna use the photos API from JSON placeholder. And what I want you to do is I want you to render out the photo gallery.
[00:00:14]
So I think there's 5,000 items that's gonna come back for you. And you need to make sure that you can loop through that, and then render out. I'd recommend rendering the thumbnail. So you'll basically inspect the data, play around with it, have fun. Just to clarify for anyone, I know this came with actually at the last workshop, I'm using TIG, which is a commandline.
[00:00:33]
Basically, it enhances the experience, so that rather than do git status, and then I have to manually add stuff, I can basically do tig status. It gives me a little terminal UI for me to work with and select files and see what's changed, for example, and then I can manually stage things by pressing u, for example.
[00:00:48]
So it's a nice, neat little terminal tool. But again, I'm not mistyping anything, just a neat little quality of life improvement. Okay, let me comit this, comit feature add todo list viewer example. Great, so now I'm gonna push up 01-begin and 01-exercise. And so what you wanna do is you're gonna wanna check out the 01-exercise branch.
[00:01:15]
And that will give you the starting point for you to go ahead and build out your photo gallery. Okay, so here we have our photo gallery. So just to sort of double check, if you look, there's our app, yep, just h1 photo gallery. So let's go ahead and configure some stuff, shall we?
[00:01:34]
First thing first is we're gonna be importing the defineNuxtComponent here. And actually, there was a question earlier regarding this. So you might see here that there's this hashtag app that's being imported from. And this looks a little bit different, because you're probably expecting some sort of node module, or some sort of library name.
[00:01:51]
So why is it this? Basically what this is it's an optimization from Nuxt that basically say, hey, I know that you're looking for this stuff, so I'm gonna automatically do it for you and just provide a simple way for you to reference it. So you don't have to go call a specific library.
[00:02:06]
So it's basically part of Nuxt's performance enhancements. And we'll get more into imports later with Nuxt, for those who might have looked a little bit further when necessary. But for now, I want everyone to just kind of understand where and how you can define those imports, so you know where it's coming from.
[00:02:21]
Okay, next thing next, we just gonna define a default what, a default Nuxt component that we use that helper function with, and then we're gonna have our data. And so our data is gonna contain what? Well, it's gonna contain an array, a photo gallery, so yeah, I'm calling them photo gallery.
[00:02:38]
And then for this photo gallery, we're gonna have a methods, right, that's gonna actually fetch the thing. So I'll just call it fetchPhotoGallery. And inside of here, we'll use our fetch method again. And this time we'll go ahead use our jsonplaceholder. But, instead of todos, I'm actually gonna call it photos.
[00:02:57]
And so if you're wondering how I know this is the path to fetch, this is not magic. Inside of here, we look at the documentation. These are actually all the resources that JSON placeholder provides for you. So I believe how can you use clones are usually built using this.
[00:03:11]
We can see there's posts, there's comments. And what's nice is there actually is some relation between them. So there'll be this comment belongs to this post, which belongs to this user. So it's a nice little kinda fake relational database for people to play around with, without the burden of actually having to host anything.
[00:03:27]
So again, hat tip off to the team who maintains this, really nice to have. Okay, so once we have the thing, the thing that I often forget, and only with my work with serverless functions that did I think I finally broke myself of it. Is that every time you fetch something from somewhere, most of the time you need to turn it into json before we can actually make it useful.
[00:03:49]
So you always have to remember to then take that response and then basically jsonify it, which is using the .json function. Once you do that, you can go ahead and then take what's returned from that, which I just call the json object, and this is where we go.
[00:04:03]
This.photoGallery = json. Now, for those who don't like chaining two different thens, there's nothing stopping you from also doing this instead. So if I just comment this out, you could also just say, all right, well, inside of this response, I'm just gonna say this.photoGallery = response.json. That would technically work too.
[00:04:25]
It's really just a stylistic preference on seeing what you would prefer. So for now, I'll just keep it consistent with what the way I did it earlier. But I think normally I probably would do it the way I just did earlier, where I went ahead and just kind of inlined everything together.
[00:04:41]
But there is something nice about making this. Usually you can tell it's very sequential. What are you doing with each step fetching? Converting it to JSON, then assigning it. There's something valid, very nice about that too. So again, not a right or wrong, definitely a preferencing, okay? And so now that we have that, we can go ahead and add our button that will go ahead and fetch set photo gallery.
[00:05:04]
And then we'll just say Fetch Data again. And then this time, again, we're just gonna assume we get that data for now. So we'll list it out. And so v-for="photo in photoGallery", and then the key here is it has an ID just like before. So I'll say photo-id, so it should be photo.id.
[00:05:23]
And then there, we will render out the photo. But actually, you know what, let me do this real quick. Let's just save this. So we go ahead and click this, you'll see, boom, a lot of stuff shows up. But, what you'll notice here is that currently the way that images are being imported is via this placeholder API.
[00:05:42]
And so if you haven't used this before, it's basically a dynamic generation of very simple blocked image. So if we were to use the URL as our image source, so if I did img src, and then use the v-bind syntax with the prefix of the colon to say that this is not a just a string anymore, it's a JavaScript variable.
[00:05:58]
We'll say photo.url, and then we save it, and then we come back. You'll notice this is huge, it's gigantic. And so it actually does have another one called I think thumbnail URL. And so if I say that, this is much smaller, this is more manageable. Now, before we did the exercise, one of the things I actually wanted to show you all as well though is one of my, actually, I think if I had to pick one feature of Vue that's my favorite, it's this.
[00:06:27]
It's computed properties. And so just to show you what that's like here, imagine you wanted to tell people how many photos were actually being shown inside of this gallery, right? Well, the way you would do that is you could create a watcher method. In some frameworks, you something has something like numberofPhotos, right?
[00:06:49]
It's gonna start out at 0. And then inside of here, you would be like, yeah, and then when I get the photo gallery, I'll do photoGallery, or this.numberOfPhotos = this.photo, or json.length, for example, right? That might be the go-to for some people when they're thinking of tracking the activity.
[00:07:08]
But, for anyone who's done this at length, you'll know that this gets really tedious. Because at some point, it's easy to mess something up from a step perspective dependencies. You're not sure if it's actually caching correctly. So sometimes you end up re-rendering giant lists that shouldn't be re-rendered.
[00:07:23]
And so frameworks should be there to help you to do that, right? And Vue does help you with that, and so with the concept of computed properties. And so what it does is it basically says, hey, here's a reactive data that I'm interested in tracking, and I want you to take care of all the performance stuff for me.
[00:07:39]
And this is probably one of the biggest wins, and I wish more frameworks. And in fact, some of them are basically steal it, use it. Because it saves so many people from basically shooting themselves in the foot when it comes to triggering re-renders, especially the longer the chain is.
[00:07:53]
So if anyone's worked with data infographics, you'll know that one change if the user decides to switch the scale will alter a ton of other different variables that changes how the chart might render. And so you don't want that to be contingent on a very brittle dependency chain and computed properties.
[00:08:11]
The beautiful part about it is that it's something that's sequential. So for example, we can move numberOfPhotos in here. And numberOfPhotos is gonna be a function, and what is a function gonna do? It's going to return this.photogallery.length. That's what it's gonna do, simple enough. And so when I come in here and let's say below this, I'm gonna have a p element, and this one is gonna say numberOfPhotos.
[00:08:38]
And then we can say photos like that. So we save that and come over here. You see that when I fetch the data, it automatically updates as it stands. And then just to show how much further you can go, you can basically be like, okay, what if I wanna find out, let's say we needed to track we know there's gonna be.
[00:08:58]
So there's album IDs inside of this data, right? So let's prove that real quick. So if I do photo here, we might wanna be like, well, what percentage of photo, or the album IDs are even versus odd, right? Cuz this is one, and then I assume there's a couple more.
[00:09:12]
I think there's 20 total. So okay, how might we do that? Well, it's actually fairly straightforward. What we would do is we would basically create a computed property called, we could say, let's see, evenAlbums, right? And we can say return this.photogallery.filter, and we'll just filter out what? We'll filter out every item that where the item.albumId and then modulo 2, which basically says if the remainder is 0, which basically means that it's even, then great, that's what we want, and this will be the full even albums.
[00:09:47]
And then from there, you can be like, well, oddAlbums is basically just the inverse of that. So I'll just copy that over and then just put the exclamation point to reverse that. And then what's cool about this now is that we can even then go here. And so inside of here, I can put in parentheses, I can say oddAlbums.length, and then just be like, odd albums.
[00:10:11]
And then I can just do evenAlbums.length, and then even albums. Save that, and so we can see when we save here, all that stuff is already cached. So actually, wait, I broke something. It's 5,000 odd albums, it should definitely be 2500. So I think I did the math wrong, filter item.
[00:10:35]
Wait, order of operations and parentheses are important. I think that's what I needed. Right, let me do that again. Yep, I was totally right. So just to explain what happened there, this is where practice is important. By only throwing the exclamation point in front of it that album ID, it was basically only applying it to this portion, and then applying the math, and it was just returning everything.
[00:10:57]
And so we want it to actually negate this entire expression, which is why the parentheses is critical. And then so on top of that, again, you can start doing some great awesome things with computer to be like, what are the percentages? Can they can just be evenAlbumPercentage? And so what you get here is you get to be able to go, well, it's gonna be this.EvenAlbums.
[00:11:18]
So you're now creating a dependency on a different computed property, and .length. And I can just basically divide that by this.numberOfPhotos. And so this will only give the fraction, but you kind of get the idea, right? If people haven't used Vue in depth, this is the one they tend to overlook.
[00:11:40]
Because when they think of tracking dependencies, they'll do watch methods and that kind of stuff, and computed properties save you so much headache and time. So I've gone ahead and demoed that. Let me go ahead and just save that, so everyone has that. And I'm gonna quickly implement a computed over here, just so that we have some parity.
[00:12:00]
And I'm just gonna do basically the completed versus not completed items. So say completedItems, and this will return this.todoList.filter where the item, we're gonna take the item, item.completed is true. And then otherwise, we have the incomplete items, or I'll call it remaining items, so that's a little bit more clear.
[00:12:26]
And then I'll add my p tag below here, wait, no, below the button. And then we'll say completedItems.length, items completed, and then we'll have the remainingItems.length remaining. So that's basically the two equivalents of the two.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops