Read this on my blog Hi there! I've got a LOT of updates to share with you this week. First off, next week Alex and I are hosting a panel on AI and Vue at Vue.js Nation! It's happening January 29-30, and you can get your free ticket here. This week I started working on the update for Mastering Nuxt. Soon, I'll be able to share more as it starts to take shape! I'll also be speaking at VueConf US in May in Tampa! I'm giving a talk on component patterns there. Lastly, if you missed it, I released a free email course on component patterns a couple months ago. You'll get 5 emails over 5 days with different patterns for building better components in Vue, covering some of the material from Clean Components Toolkit. Of course, there are more tips, articles, and a new podcast episode for you to enjoy. — Michael 🔥 Dynamic Directives Vue lets us use dynamic arguments with directives: <template> <WowSoDynamic v-bind:[somePropName]="somePropValue" v-on:[customEvent]="handleClick" /> </template>
When the argument evaluates to null , the attribute or event is removed. This makes a really convenient way of making them conditional: <!-- LinkComponent.vue --> <template> <a :href="url" v-bind:[targetAttr]="'_blank'" > <slot /> </a> </template> <script setup> import { computed } from 'vue'; const { newTab } = defineProps({ newTab: { type: Boolean, default: false, }, url: { type: String, required: true, }, }); // If newTab === false set this to null const targetAttr = computed(() => newTab ? 'target' : null); </script>
By using a computed prop, we set targetAttr to null if newTab is false . Either we add the target attribute with a value of _blank , or we don't add it. 🔥 Destructuring and Reactivity Destructuring a value from a reactive object will break reactivity: const myObj = reactive({ prop1: 'hello', prop2: 'world' }); const { prop1 } = myObj; // prop1 is just a plain String here
The reactivity comes from the object itself and not the property you're grabbing. You must use toRefs to convert all of the properties of the object into refs first, and then you can destructure without issues. This is because the reactivity is inherent to the ref that you're grabbing: const myObj = reactive({ prop1: 'hello', prop2: 'world' }); const { prop1 } = toRefs(myObj); // Now prop1 is a ref, maintaining reactivity
Using toRefs in this way lets us destructure our props when using script setup without losing reactivity: const { prop1, prop2 } = toRefs(defineProps({ prop1: { type: String, required: true, }, prop2: { type: String, default: 'World', }, }));
🔥 Fine-grained Loading API in Nuxt In Nuxt we can get detailed information on how our page is loading with the useLoadingIndicator composable: const { progress, isLoading, } = useLoadingIndicator(); console.log(`Loaded ${progress.value}%`); // 34%
It's used internally by the component, and can be triggered through the page:loading:start and page:loading:end hooks (if you're writing a plugin). But we have lots of control over how the loading indicator operates: const { progress, isLoading, start, // Start from 0 set, // Overwrite progress finish, // Finish and cleanup clear // Clean up all timers and reset } = useLoadingIndicator({ duration: 1000, // Defaults to 2000 throttle: 300, // Defaults to 200 });
We're able to specifically set the duration , which is needed so we can calculate the progress as a percentage. The throttle value controls how quickly the progress value will update — useful if you have lots of interactions that you want to smooth out. The difference between finish and clear is important. While clear resets all internal timers, it doesn't reset any values. The finish method is needed for that, and makes for more graceful UX. It sets the progress to 100 , isLoading to true , and then waits half a second (500ms). After that, it will reset all values back to their initial state. 🔥 Strategy Pattern The Strategy Pattern is ideal for handling complex conditional logic in Vue applications. It allows dynamic switching between different components based on runtime conditions, which can improve the readability and flexibility of your components. <template> <component :is="currentComponent" /> </template> <script setup> import { computed } from 'vue'; import ComponentOne from './ComponentOne.vue'; import ComponentTwo from './ComponentTwo.vue'; import ComponentThree from './ComponentThree.vue'; const props = defineProps({ conditionType: String, }); const currentComponent = computed(() => { switch (props.conditionType) { case 'one': return ComponentOne; case 'two': return ComponentTwo; case 'three': return ComponentThree; default: return DefaultComponent; } }); </script>
To learn more about this pattern and 20 more, check out Clean Components Toolkit. 🎙️ #043 — The Year in ReVue (with Daniel Roe) Of course, we can't fully start into 2025 with a little ReVue of the past year. And to make sure to catch all the highlights, Alex is joined by Daniel Roe, full-time open source developer and lead of the Nuxt team to go through some notable events of 2024 in the Vue and Nuxt ecosystem. In addition to the shining moments of 2024, don't miss out a deep dive into web fonts, learn why Nuxt 4 isn't out yet if you didn't know already and maybe even get a slight glimpse into 2025 and Nuxt 5. Watch on YouTube or listen on your favorite podcast platform. In case you missed them: 📜 Quickly Build Fullstack Vue Apps with Directus Directus is a powerful headless CMS that can be used to quickly build fullstack Vue apps. In this article, we'll go over how I used Directus and Nuxt to build a survey app — all without writing a single line of backend code. Check it out here: Quickly Build Fullstack Vue Apps with Directus 📜 Understanding Environment Variables in Nuxt Environment variables are a crucial part of any application, and Nuxt makes it easy to manage them. In this article, we'll go over how to set up and use environment variables in Nuxt. Check it out here: Understanding Environment Variables in Nuxt 📅 Upcoming Events Here are some upcoming events you might be interested in. Let me know if I've missed any! Vue.js Nation 2025 — (January 29, 2025 to January 30, 2025) The biggest and only 100% free Vue.js conference in the world! I am giving a talk on composable design patterns, and hosting a panel with Alex Lichter. Check it out here Vuejs Amsterdam 2025 — (March 12, 2025 to March 13, 2025) The biggest Vue conference in the world! A two-day event with workshops, speakers from around the world, and socializing. Check it out here VueConf US 2025 — (May 13, 2025 to May 15, 2025) Giving a talk here on component patterns! A great Vue conference, this year held in Tampa. Two days of conference talks, plus a day for workshops. Check it out here 💬 Great Developers "Every great developer you know got there by solving problems they were unqualified to solve until they actually did it." — Patrick McKenzie 🧠 Spaced-repetition: Check Vue's Version 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. Did you know that you can easily check the version of Vue at runtime? import { version } from 'vue'; if (version.split('.')[0] === '2') { console.log('Uh, this app is gonna crash.'); console.log('Upgrade to Vue 3!'); }
🔗 Want more Vue and Nuxt links? Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links. Sign up for it here. p.s. I also have a bunch of products/courses: |
评论
发表评论