Hey!
Three things for you.
First, I want you to go and subscribe to Michael Hoffmann's Vue newsletter, because the only thing better than getting a newsletter from one Michael is getting newsletters from two Michaels.
But also, his newsletter is fantastic — he fills it with tons of great links on Vue and Nuxt, as well as some about the broader web ecosystem.
So if you sign up to both of ours, you'll get great tips from mine, and the latest and greatest links from his.
Sign up for it here.
Second, I'm releasing the big update to Clean Components Toolkit next week on June 5th!.
I've added 20% more content — 3 new tools (now 21 in total) and 3 new bonus videos.
If you want to learn about design patterns in Vue, there is no better resource out there.
It will also be 35% off from June 5th to June 8th!
You can check out a live preview here, and go to the landing page here.
Third, I've written an article on my favourite ways to learn Vue in this article. If you're interested in other courses besides Clean Components Toolkit, check this one out.
Have a fantastic week!
— Michael
Vue Tips Collection 2
Maybe you just want to stay on top of the latest features, remind yourself of interesting things Vue can do, and get daily inspiration.
Vue Tips Collection is a beautiful book of 118 concise tips, as well as a daily email to get your creative juices flowing.
Check out Vue Tips Collection
🔥 Creating an If...Else
Component
Ever thought about making an If...Else
component in Vue, despite having v-if
, v-else
, and v-else-if
?
Here's a quirky experiment that explores this idea:
<If :val="mainCondition">
<template #true>Render if true</template>
<Else :if="false">Else if condition</Else>
<template #false>Otherwise render this</template>
</If>
This setup uses Compound Components, default and named slots, and even render functions to achieve a flexible If...Else
logic.
The If
component checks a condition and decides which slot (true
, false
, or Else
) to render.
The Else
component — a Compound Component — allows for an else if
condition.
I have a detailed write up about this component on my blog.
Here's a simplified version for a cleaner API:
<If :val="condition">
<True>Truth</True>
<Else :if="elseCondition">Else slot</Else>
<False> What up false branch! </False>
</If>
This experiment is a fun way to dive deep into Vue's features like slots, reactivity, and component communication. While it might not replace the built-in directives, it's a great learning exercise and could inspire other creative component designs.
Check out the demo and maybe even try implementing your version: Vue If...Else Component Demo
Remember — experimenting with "weird" ideas is a fantastic way to deepen your understanding of Vue!
🔥 Computed Props in Your Template: v-memo
Vue 3.2+ gives you fine-grained control over template re-rendering using v-memo
:
<div v-memo="[varA, varB, varC]">
<!-- ... -->
</div>
This works much the same as a computed prop does. An element with v-memo
is only re-rendered when the array changes, but otherwise, it caches (or memoizes) the result.
When it's used with v-for
you can selectively re-render only the parts of a list that have changed:
<div
v-for="item in list"
:key="item.id"
v-memo="[item.id === selected]"
>
<!-- ... -->
</div>
Here, we only update the nodes that go from selected to unselected or vice versa. Much faster if you're dealing with extremely long lists!
But since Vue is already so efficient with re-renders, you shouldn't need to use v-memo
often.
It's definitely a helpful tool to help you get more performance — when you really need it.
Check out the docs for v-memo.
🔥 Component Variations with the Base Component Pattern
The Base Component pattern is one of my favourite ways to make many different versions and variants from a single component.
It has a few basic steps:
- Create your base component
- Wrap it with another component to get a variant of the original
- Repeat step 2 as many times as you need
Here's an example, creating a DisabledButton
variant out of a BaseButton
component:
<!-- DisabledButton.vue -->
<template>
<!-- Never forget how to create this disabled button.
Package it up using the Base Component pattern. -->
<BaseButton
type="disabled"
disabled
>
<!-- You can't accidentally use the wrong icon now.
It's provided here for you -->
<template #icon>
<Icon type="disabled" />
</template>
</BaseButton>
</template>
You can use this pattern in many different ways:
- Lock down props — take a
Button
component and hard code a few props to get a DisabledButton
. Now you can just use the DisabledButton
directly without fiddling with all the necessary props each time. - Lock down slots — create an
InfoButton
variant where the icon passed to the Button
is always the same. So now, if you ever need to change the icon (or anything else), you can do it in one place. - Simplify props — sometimes components end up with dozens of props, primarily for edge cases. Instead, create a
BaseButton
with all the props, and a Button
that passes on only the most common ones. This is a lot safer and easier to use, and the documentation for this component is easier to read.
I've included more on this pattern in Reusable Components.
📜 Optimizing a Vue App
Michelle does an excellent job of giving a high-level overview of best practices to keep your app speedy.
Great as a starting off point or checklist for anyone looking to optimize their Vue app.
Check it out here: Optimizing a Vue App
📜 Build 3D Scenes Declaratively with TresJS Using Vue
Alvaro has done some really impressive work with TresJS, a 3D library for Vue.
In this article he showcases just how easy it is to create 3D scenes in Vue when using TresJS.
Definitely check it out if you're interested in 3D development with Vue!
Check it out here: Build 3D Scenes Declaratively with TresJS Using Vue
💬 Carpentry vs. Software
"In carpentry you measure twice and cut once. In software development you never measure and make cuts until you run out of time." — Adam Morse
🧠 Spaced-repetition: Example of a Composable Using the Options Object Pattern
The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨🔬
Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.
Let's create a useEvent
composable that will make it easier to add event listeners.
We'll use the EventTarget.addEventListener
method, which require the event
and handler
parameters. These are the first two required parameters:
export function useEvent(event, handler) {};
But we also need to know which element to target. Since we can default to the window
, we'll make this our first option:
export function useEvent(event, handler, options) {
// Default to targeting the window
const { target = window } = options;
};
Then we'll add in onMounted
and onBeforeUnmount
hooks to setup and clean up our event:
import { onMounted, onBeforeUnmount } from 'vue';
export function useEvent(event, handler, options) {
// Default to targeting the window
const { target = window } = options;
onMounted(() => {
target.addEventListener(event, handler);
});
onBeforeUnmount(() => {
target.removeEventListener(event, handler);
});
};
We can use the composable like this:
import useEvent from '~/composables/useEvent.js';
// Triggers anytime you click in the window
useEvent('click', () => console.log('You clicked the window!'));
The addEventListener
method can also take extra options, so let's add support for that, too:
import { onMounted, onBeforeUnmount } from 'vue';
export function useEvent(event, handler, options) {
// Default to targeting the window
const {
target = window,
...listenerOptions
} = options;
onMounted(() => {
target.addEventListener(event, handler, listenerOptions);
});
onBeforeUnmount(() => {
target.removeEventListener(event, handler, listenerOptions);
});
};
We keep listenerOptions
as a pass-through, so we're not coupling our composable with the addEventListener
method. Beyond hooking up the event, we don't really care how it works, so there's no point in interfering here.
Now we can take advantage of those extra options:
import useEvent from '~/composables/useEvent.js';
// Triggers only the first time you click in the window
useEvent(
'click',
() => console.log('First time clicking the window!'),
{
once: true,
}
);
This is a pretty basic composable, but by using the Options Object Pattern it's easily configurable and extendable to cover a wide swath of use cases.
p.s. I also have four products/courses: Clean Components Toolkit, Vue Tips Collection 2, Mastering Nuxt 3, and Reusable Components
评论
发表评论