More Vue design patterns for you!
I've added 20% more content to Clean Components Toolkit, and I'm celebrating by giving you a big 35% discount until June 8th! 🎉
It now has a total of 21 patterns on using Vue, which is around 11 hours of content.
I wrote about 12 of them in a new article I just published.
You can check out the course here to see what it's all about. There's also a live preview if you want to sample some of the patterns and tools (you'll have to login with your Github).
Each design pattern comes with:
Get Clean Components Toolkit now!
— Michael
If you find yourself needing to force Vue to re-render a component, chances are the reactivity in your app is broken somewhere.
But, if you have a valid use case, forceUpdate
is not working, or you simply need to get things working quickly, the best way to do this is through the Key Changing Technique:
<template><MyComponent :key="componentKey" /></template><script setup>import { ref } from 'vue';const componentKey = ref(0);const changeKey = () => {componentKey.value += 1;};</script>
Here’s how you’d do it with the Options API if you’re not using Vue 3 or not using the Composition API:
export default {data() {return {componentKey: 0,};},methods: {changeKey() {this.componentKey += 1;}}}
Using the key
attribute lets us give Vue more information so it can correctly remove and replace DOM elements on the page. Because of the reactivity system, Vue can get confused about which elements need to be replaced in the DOM and which need to stay.
When we change the value of our key
, Vue knows that this is a “new” component. It will destroy the existing component and then create and mount an entirely new one.
Problem solved!
But before you reach for this solution, make sure that there isn’t a reactivity issue in your application. This should only be used as a last resort, and is not a recommended approach.
Here's the best way to think about scoped slots:
Scoped slots are like functions that are passed to a child component that returns HTML.
Once the template is compiled, they are functions that return HTML (technically vnodes
) that the parent passes to the child.
Here's a simple list that uses a scoped slot to customize how we render each item:
<!-- Parent.vue --><template><ScopedSlotList :items="items"><template v-slot="{ item }"><!-- Make it bold, just for fun --><strong>{{ item }}</strong></template></ScopedSlotList></template>
<!-- ScopedSlotList.vue --><template><ul><liv-for="item in items":key="item"><slot :item="item" /></li></ul></template>
We can rewrite this example to use a function instead of a scoped slot:
<!-- Parent.vue --><template><ScopedSlotList:items="items":scoped-slot="(item) => `<strong>${item}</strong>`"></template>
<!-- ScopedSlotList.vue --><template><ul><liv-for="item in items":key="item"v-html="scopedSlot(item)"/></ul></template>
I decided to see if I could make a v-for
component using only the template. Along the way, I discovered how to use slots recursively, too.
This is what the component looks like:
<!-- VFor.vue --><template><div><!-- Render the first item -->{{ list[0] }}<!-- If we have more items, continue!But leave off the item we just rendered --><v-forv-if="list.length > 1":list="list.slice(1)"/></div></template>
If you wanted to do this with scoped slots — and why wouldn't you?! — it just takes a few tweaks:
<template><div><!-- Pass the item into the slot to be rendered --><slot v-bind:item="list[0]"><!-- Default -->{{ list[0] }}</slot><v-forv-if="list.length > 1":list="list.slice(1)"><!-- Recursively pass down scoped slot --><template v-slot="{ item }"><slot v-bind:item="item" /></template></v-for></div></template>
Here is how this component is used:
<template><div><!-- Regular list --><v-for :list="list" /><!-- List with bolded items --><v-for :list="list"><template v-slot="{ item }"><strong>{{ item }}</strong></template></v-for></div></template>
For a more detailed explanation of this example and nested slots, check out my blog post on it:
How to Use Nested Slots in Vue (including scoped slots)
In this article I explore how to write a composable in Nuxt that can be used to cache data when using fetch.
It's a fun one! We dig into TypeScript, composition API, and Nuxt 3's useFetch
composable.
Check it out here: Writing a Cache Composable in Nuxt 3
In this great article, Lachlan takes us through writing our own ref
implementation from scratch.
He gets straight to the point, and the test-driven style makes it easy to understand what we're trying to accomplish.
If you want a deeper understanding of how the composition API works, it's definitely worth a read.
Check it out here: Building Vue 3 Reactivity from Scratch
VueConf CN 2024 — July 6, 2024
PragVue 2024 — September 17, 2024
Vuejs.de Conf — October 8, 2024 to October 9, 2024
Vue Fes Japan 2024 — October 19, 2024
VueConf Toronto 2024 — November 18, 2024 to November 20, 2024
"Testing can only prove the presence of bugs, not their absence." — Edsger W. Dijkstra
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.
I always forget this, so this tip is mostly for me — hopefully, I won't have to keep looking this up!
We have 3 types of for
loops in Javascript:
for...in
for...of
for
But how do you know which one to use?
For iterating through properties of an object, use for...in
:
const numbers = {'one': 1,'two': 2,'three': 3,};// We get the properties of the object, not the valuesfor (const number in numbers) {console.log(number);}// Prints: 'one' 'two' 'three'
Items in a list (also called an iterable object) like an Array or Set, we use for...of
:
const numbers = ['one', 'two', 'three'];// We get each of the elements in the Arrayfor (const number of numbers) {console.log(number);}// Prints: 'one' 'two' 'three'
You can use for...in
with an Array since all the indices are just the object's properties. But you may not get them in the correct order, and you'll also get any other properties the Array has :/
And you know how to use a regular old for
loop, which lets you have a lot more control with some extra typing.
Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links.
p.s. I also have four products/courses: Clean Components Toolkit, Vue Tips Collection 2, Mastering Nuxt 3, and Reusable Components