Check out a free preview of the full Production-Grade Vue.js course:
The "Component Design Patterns" Lesson is part of the full, Production-Grade Vue.js course featured in this preview video. Here's what you'd learn in this lesson:

Ben covers two component design patterns. The Vendor Component Wrapper pattern recommends wrapping vendor components in a custom Vue component to encapsulate the API and functionality. The Transparent Component pattern uses the inheritAttrs property to allow props, attributes and listeners to get passed through the parent element of a component.

Get Unlimited Access Now

Transcript from the "Component Design Patterns" Lesson

[00:00:00]
>> Next, we're gonna talk about some design patterns when it comes to components that are really useful at scale. And the first of which is the vendor components wrapper. So here we have a simple component that's using these Font Awesome icons from the Font Awesome library, right? We have water, earth, fire, and air.

[00:00:20] And usually I do this in person, because someone's chuckling, and they recognize the Avatar reference. And if you do, I'm glad to meet fellow Avatar fans. But, so anyways, we have these icons here. And the problem is, though, you can imagine though, as you go through the various, as you go through your application?

[00:00:40] The problem is, when you're using these Font Awesome icons throughout your app, you're thinking, I'm reusing it, it's great. The problem is, what happens when you actually need to refactor these. And it's this scary moment because, it's not even just refactor, right? Because if it was as simple as swap out Font Awesome for something, it'd be one thing.

[00:00:58] But I think we all know that when it comes to design, the requirements are rarely so black and white. Sometimes you might need to import, for example, your own custom icon. And you might actually need, maybe you wanna swap it out for material. And so if you have a large app, somebody swapping Font Awesome icons for material icons would be a huge, that PR would be monstrous.

[00:01:17] And you'd have to be really careful about how you handle that. Well, that's why going forward, we represent basically, when you're using vendor, of course components, right, something that's coming from a third party, always wrap it inside of your own component. So even though Font Awesome in that example, right, had its own API for how Font Awesome works, that's fine.

[00:01:38] But inside of your application, in this case, you should be using a BaseIcon.vue. And then that will go ahead, and then you can then toggle, right? You can do that, okay, either in this case, we wanna manually define that if the source is Font Awesome, then we'll use the Font Awesome icon component, and we'll pass in the name, just like you normally would expect.

[00:01:57] On the other hand, by default, by default, what we'd really want is just to use our custom icon that the designer's provided for us. And so this is really critical, because then, now going forward, if someone wants to add another library, it is as simple as adding a v-if-else, or v-else-if.

[00:02:16] So v-else if source equals material design, no problem, you're good to go. You don't need to reconfigure everything in order to make this work. And vice versa if, in the future, you need to upgrade or change anything. The changes become smaller in scope, and so again, when we think about enterprise production-grade apps, it's really about easing that process of getting features through.

[00:02:38] And so as we all know, right, pull requests are a big part of our code review process. So the easier you can make code reviews, the faster things go through. And vendor wrapper icons are one of those ways to just shorten the code review process, and to focus on the things that actually matter.

[00:02:52] Not whether 200 lines of replacing Font Awesome icons actually broke anything, that would be terrifying. So the next design pattern that is really worth mentioning is the transparent component wrapper design pattern. And so you can imagine that, right, over time, forms is one of the things that a lot of us have to build out, and a lot of times, we need to customize the input.

[00:03:18] Native HTML just doesn't do the trick. And so in the BaseInput example, we can see that we have this input, right, type="text". And what we've done is we did the v-bind technique, where we're spreading out all of the attributes, right, including all of the props onto our input.

[00:03:34] And we wanna listen to all of the listeners, so that's why we do the v-on="$listeners". And so when you do this originally, you would probably think that, okay, so if I call Base Input, and I'm gonna pass it filterData, the label will be Filter results, and the placeholder's gonna be Type in here.

[00:03:54] Your expectation is probably that, well, obviously, I want this on the input, so they should go here. But by default, it'll actually go onto the root element. So this is one of the restrictions that came with Vue 2, right? Because at the time, it was basically, Vue couldn't tell where things were going with multi-root components.

[00:04:13] And so basically, this is why, out of the box, it always runs to the single root, the root node, as far as BaseInput is concerned. Now, this is not what we want, right, because this'll basically break what we need. And so what we actually need to do is, inside of our script block, we actually need to define that we want to disable basically attribute inheritance.

[00:04:35] And so you can see that inheritAttrs on the bottom is equal to false. And when you do that, that will then appropriately allow those v-binds to work in v-on correctly, and sort of reroute everything to where you've defined it to. Otherwise, it's automatically gonna go to that root div.

[00:04:54] So yep, so then they'll be passed to the element instead, and as long as you prevent Vue from assigning attributes to the top-level element, you will be good to go. Okay, now, the thing is, though, is that this syntax here is specific to Vue 2. As we know, a lot of times, when frameworks upgrade, sometimes things can get complicated, things change a lot.

[00:05:20] But one of the core principles that Vue 3 tries to uphold is that we wanna take what we know people are doing a lot, and we wanna make it even simpler. And so in this case, for Vue 3, going forward, instead of having to do all that, props and attributes have basically been fused together, and as well as the listeners.

[00:05:37] So all three of those things are now under one attribute, so the attribute object, basically. And so in Vue 3, all you gotta do, as long as you v-bind your attrs to this input, in this particular case, everything will work as expected. So it simplifies the syntax, and there's sort of less things for you to configure.

[00:05:55] Granted, if you need to break it up, you can still break it up, right? Inside of attrs, there's still listeners, there's still props, and you can break them up as you need. But the syntax is much simpler now.