Intermediate Vue

Component Patterns

Ben Hong
Pandan Studio
Intermediate Vue

Lesson Description

The "Component Patterns" Lesson is part of the full, Intermediate Vue course featured in this preview video. Here's what you'd learn in this lesson:

Ben discusses managing dependencies with third-party libraries and frequent design changes. He demonstrates a vendor wrapper for handling custom icons and introduces the v-bind/v-on object syntax for dynamic props and events.

Preview
Close

Transcript from the "Component Patterns" Lesson

[00:00:00]
>> Ben Hong: This is something we should all be really familiar with. But when it comes to growing as a VUE developer, a lot of times most of us are not so lucky as to inherit a brand new code base, right? We usually have things that we're working with that are brand new, or more importantly, you know, managers want us to ship quickly, so we bring in third party libraries and we wrap stuff up.

[00:00:16]
But there is a question of how we properly manage those dependencies, because any of us who've done this long enough knows that redesigns often happen. And so having to rip out internals and refactor things is something that's common. And so what are some techniques we can do to kind of manage this particular problem?

[00:00:31]
All right, so let's go and take a look at the code that we have so inside of our app. Again, this is with our standard Vue 3 app. We're using Vue 3 router here. You'll notice here that we have a lot going on. Basically, we're using Daisy UI from a tailwind perspective.

[00:00:46]
So, that's the UI library being used. And one of the things that's being used a lot, and one that I think we can all share as a common pain point, is this icon component. This is from Daisy ui. In fact, this is from Iconify. So if we look at the number of instances of icon, you can see that it's actually used.

[00:01:04]
Well, it's used quite a lot. So this might not seem like a big deal at first, but as we know, design requirements do change and oftentimes they'll come in and they'll want a random one off, or they'll want something changed about it. And so the question boils around, how do we actually manage those changes and requests?

[00:01:21]
So let's say, for instance, that a designer has discovered this amazing resource which, if you are not aware of, you should also be aware of. And it's called icons.js.org it's basically this collection of free icons across a lot of different ones. So, for example, if I want to look up like Mountain icon, they'll give me a bunch from the different libraries.

[00:01:44]
What's cool about this is that I can pick any one of these. Let's choose this one, for example. Then it'll tell me where it came from. But then it can also let you generate basically like the svg or in this case we can actually just click and copy the view component.

[00:01:59]
It'll just populate that for you. So let's say the designer wants this because what they want to do is they want to replace this icon that we have in the upper left. They want to replace it with a mountain instead. So we know for a fact that this icon does not exist inside the iconify view.

[00:02:16]
So what you might be originally tempted to do is probably just either dropping the SVG or a custom component just in that one point. But as we know with enterprise app, things bloat really quickly. Things get reused. And so what we want to do is try to as much as possible, maintain a single source of truth.

[00:02:30]
That way we can centralize everything. And more importantly, when changes are being made or being swapped out, it's a lot easier to refactor and more importantly, easier to maintain. So how might we do this? So, first thing first, I'll go ahead and create the component here inside of the Components folder.

[00:02:49]
I usually like to create a dedicated icons folder. So I'll call this iconmountain View and then I'll just paste basically the template that they generated for us earlier. So you see here we just have a simple svg. It has some widths defined as well as a vue box.

[00:03:07]
And so overall it looks fairly straightforward. So, I'm just go ahead and actually switch the name here just to IconMountain to simplify it. And so as I mentioned before, one of the things we want to do is centralize the work that we're doing, because as we saw when we looked at the icons, there are just so many different variations here.

[00:03:25]
There's a lot of different widths going on, as well as trying to figure out, okay, what exactly are we standardizing on? Especially if you want to start with like, all icons should start with 20 by 20 size, for example, that would be pretty tricky to do, especially if you're just doing a search and replace the pattern that I generally recommend when it comes to this is known as a vendor wrapper component.

[00:03:48]
What that essentially does is it allows us to basically create a wrapper around the UI library components that we're using as a way to basically provide this single source of truth. The way that would look is that we would go ahead and create a baseicon component. And so, I'm gonna use a little snippet here that I have.

[00:04:07]
Basically this is a VS code snippet. And so just in case anyone's not sure what this is, and it basically allows me to scaffold the single file component, basically instantly like that.
>> Speaker 2: How do you do that? SFC shortcut.
>> Ben Hong: The which one?
>> Speaker 2: Sfc.
>> Ben Hong: Yes. Cool.

[00:04:24]
I'm glad you asked about this. So when you're in VS code, if you go to your extension. So, I'll do it the command prompt way. So command shift P, then we'll go to our extensions. Can I just see my extensions? The way I do it is command KE or X.

[00:04:41]
But anyways, it's right here. Sarah Drasner, who used to be on the VUE core team and now is at Google, she created this thing called Vue VS Code snippets, highly recommended as an extension. I actually am one of the maintainers. It has a bunch of different, basically, snippets for things that you like to use.

[00:05:05]
So, you can see here that you do. Okay, let's see. Vbase ss, right? So if I come inside here and I'm inside of my view V base, so you see here there's like a bunch of different ones you can choose from and then it'll just kind of. You can basically customize it.

[00:05:23]
So the thing though is that you can install it, definitely play around with it. But what I really love about the repo is that once you look at it and you find one that you're like, I like that one, I just want to tweak it a little bit.

[00:05:32]
VS code snippets are actually fairly easy to create on your own because then basically you just copy it. Be like, I don't use scss, I use less, or post CSS because I use tailwind, whatever. Then you don't have to deal with the boilerplate that comes with it. Okay, so we know a couple of things.

[00:05:48]
We know, one, we want to make sure we migrate all of the icons over Iconify. And so let's go ahead and do that first. So let's search so we have this import that we're going to grab here. And then we know as well that this is the general structure that we see, at least for the Iconify one.

[00:06:11]
And so what's interesting though is that you'll see here that in the Iconify icon, they use icon in order as like the prop to designate what the name is. But if you've used other icon libraries as well, you'll notice that the API for it is different as well.

[00:06:25]
That's one of the reasons the vendor wrapper icon can be very advantageous. Because for our example with the MountainIcon, right, so I inch for the IconMountain, for example. What we probably want to do then is we need to do two things. One, we need to set what our default is and then basically what our override is going to be.

[00:06:47]
So the default is at this point, going to be Iconify View, because this is obviously where a bulk of our icons are living. So what I like to do generally in this situation is we define a prop here, where we basically have the source be a type of string, and then I default it to the main library that, that we're actually using.

[00:07:13]
And so in this regard, so here we can say V if source is equal to Iconify, and then we go ahead and then designate the rest of it. So we can say, okay, how do we want this API to look? Do we want to just call it icon?

[00:07:31]
Or. In this case, I do think what I've seen more normally, especially when it comes to icon naming, is just the name itself. So then we can have a name string here and we'll go ahead and require it. And then we can bind this directly to name as well.

[00:07:56]
And then we can go ahead. And then width and height are also very common as well. So we'll go ahead and also just go ahead and designate those as well. So then default 20 and then we'll just copy this and make that height. And here we have the beginnings of our wrapper icon.

[00:08:21]
Okay, so of course, the question is, now we need to deal with this icon mountain. How do we deal with this? Now, if we think about this from another perspective, while it's easy to say, all right, what we're going to do is we're going to bring icon mountain here, down here, and we're just going to basically, vls.

[00:08:40]
You could do something as simple as that if you really wanted to. However, obviously, when it comes to scale, it's not going to work as well as you think. So what we ultimately want to do is provide the user the ability to basically define their name, and then we are going to dynamically import that as it goes.

[00:08:56]
So the way you do that is there is a helper function in Vue called defineasync component. And so, what that's gonna allow you to do is basically define a path that can be brought in based on how it's defined. So what I'm going to do here is then also I'm going to bring in computed as well, because we're going to go ahead and make.

[00:09:15]
First we need to refer to our props. So, I'm gonna assign it to a variable, and so then we're gonna say to our custom icons, it's gonna be a computed value where basically, if props source is equal to. Or basically in this case, we can say not equal to Iconify, we could even go that far to say that at this point, then we could say basically return define async component.

[00:09:40]
And then that takes a function that returns basically an import statement of the path. So in this case it'll be components. I believe I put it in icons, yep. And then slash and then I can go ahead and just do the props.name.view. And then otherwise we just return null.

[00:10:03]
Okay, let's see. So, let's see it's, cannot find corresponding type declarations. That is fine for now because this is dynamically being brought in. I see what it is. Hang on, do. There you go. Yay for syntax highlighting. Okay, so now that you have this, what you can do is Vue has the built in dynamic component.

[00:10:26]
So now we can say basically say for the component, dynamic component. We're going to make that equivalent to using the is parameter is prop to say custom icon. And so we're going to do now then is we're going to go ahead and find that header that we had.

[00:10:43]
Do, so App.vue header here. So we have this icon here right with the target. We no longer want that. What we're going to do instead is we're just going to import our base icon. And so this will go ahead and drag import that directly right here. Although sometimes it does it incorrectly and as a type.

[00:10:59]
So that's actually a little bit frustrating sometimes. And then I'll say source. I like to say custom. And then the name is going to be icon mountain. Now that we save, you can see. Voila, we have our base icon. This pattern is incredibly effective for essentially helping you centralize these things.

[00:11:23]
I won't go through the process right now of doing all the replace of the base icon. I'll do that later when we're doing exercises. This is the concept of the vendor wrapper. Now the other technique that I do want to mention here with the base icon is. Let me cue the slide here.

[00:11:42]
It's known as the v-bind/v-on syntax. So here typically you would have like. Again, let's say we wanted to customize the width to like 30 and then the height also to 30. You notice here one it's broken because partially because on the base icon I did not define the various props on here directly.

[00:12:03]
So I'll go ahead and just copy this over real quick just so we can get rid of that error string is not assignable to number. All right, we'll deal with that later. So, what you can do actually is that, in the event that you wanted to make this dynamic, right?

[00:12:20]
So, let's go ahead and say, for example, that we have a custom source and it was make this a ref real quick, just to demonstrate this. And then we'll call this font awesome. And then we had a const Custom name equals ref. And we'll call this Upside Down Mountain.

[00:12:41]
And then we had const custom width, which is a ref of, let's say 40. Then we have our custom height. So one way you could define this is you could go ahead and come in and then V bind each one of these individually. So this should look familiar to most people, this one custom height, you could do it like this.

[00:13:13]
However, a lot of times when we're working with dynamic components, you can't always control what attributes are being. If you're swapping out components, you're gonna be swapping out different properties, different events. And so if you're hard coding them like this, you're going to have basically extra code being passed to your components that don't need to be.

[00:13:29]
And so what you can do instead is this can all actually be shortcutted to this vbind syntax, where you basically have an object. And this is where the thing that we see here would be equivalent to this. And then what's nice about this is you can take this one step further in that if we just assume, again, let's just say props.

[00:14:06]
Let's see. That's fine. Props object. And then you just basically did the source, the name and then the width and the height. Here, again, assuming this width and height, this whole thing can be swapped down into just props object. And this is important. The reason I wanted to go over this is because this is going to be very common as we go through the rest of the patterns, where we're going to be basically doing vbind on dynamic attributes where we don't know what's being passed.

[00:14:50]
And so we basically need VUE to just spread it out on the component and we decide what's going on. I won't demonstrate this explicitly, but in the event, you have multiple events as well, like mousedown, key up, whatnot, there's an equivalent for, call it the events object, right?

[00:15:07]
Where you can just write an object that pairs your events to whatever you want of functions you want to assign them to. So, both these are basically what they call the v-bind/v-on object syntax.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Start a 5-Day Free Trial