Read this on my blog In only a few hours I'll be giving a talk on composable design patterns at Vue.js Nation! Go get your free ticket here. Tomorrow, Alex Lichter and I will be hosting a panel on AI and Vue development as well — you won't want to miss that one (you'll be able to ask questions live). I also recorded a video on how I use AI to quickly learn new libraries. And I'm steadily working on updating Mastering Nuxt 3 — this will be a free update to everyone who already bought it (and there's currently a 30% off sale going on). This is some of what I've done so far: - Upgraded everything to Nuxt 4 (super easy, thanks to the Nuxt team)
- Refactored to use layers
- Using
NuxtImg for images (it was in beta when MN3 was published) - Simplifying (and improving) Supabase auth usage with some new features
- Simplified Prisma types with the
GetPayload utility type What kinds of things would you like to see in the updated version? — Michael 🔥 Lightweight State Management We can add computed and methods directly on to a reactive object: const counter = reactive({ count: 0, increment() { this.count += 1; }, decrement() { this.count -= 1; }, });
This works because this is set to the object that the method is accessed through, which happens to be the reactive object. Vue's reactivity system uses Proxies to watch for when a property is accessed and updated. In this case, we have a small overhead from accessing the method as a property on the object, but it doesn't trigger any updates. If we had a whole series of counters we can reuse this over and over: const listOfCounters = []; for (const i = 0; i < 10; i++) { const counter = reactive({ id: i, count: 0, increment() { this.count += 1; }, decrement() { this.count -= 1; }, }) listOfCounters.push(counter); }
In our template we can use the counters individually: <div v-for="counter in listOfCounters" :key="counter.id"> <button @click="counter.decrement()">-</button> <button @click="counter.increment()">+</button> </div>
Instead of making the entire object reactive, we can use ref to make only our state reactive: const counter = { count: ref(0), increment() { this.count.value += 1; }, decrement() { this.count.value -= 1; }, };
This saves us a small and likely unnoticeable overhead. But it also feels somewhat better since we're being more thoughtful with our use of reactivity instead of spraying it everywhere. Here's our example from before, but this time I'm going to add in a factory function to make it more readable: const createCounter = (i) => ({ id: i, count: ref(0), increment() { this.count.value += 1; }, decrement() { this.count.value -= 1; }, }); const listOfCounters = []; for (const i = 0; i < 10; i++) { listOfCounters.push(createCounter(i)); }
Of course, we can use a factory method with the previous reactive method as well. 🔥 Reassigning Template Refs Reassigning values can cause issues when using the simplest form of template refs: <template> <div> <h1 ref="heading">This is my page</h1> </div> </template>
In this case, we can't use a reactive object at all: const heading = reactive(null); watchEffect(() => console.log(heading)); // "null"
When the component is first instantiated, this will log out null , because heading has no value yet. But when the component is mounted and our h1 is created, it will not trigger. The heading object becomes a new object, and our watcher loses track of it. The reference to the previous reactive object is overwritten. We need to use a ref here: const heading = ref(null); watchEffect(() => console.log(heading.value)); // "null"
This time, when the component is mounted it will log out the element. This is because only a ref can be reassigned in this way. It is possible to use reactive in this scenario, but it requires a bit of extra syntax using function refs: <template> <div> <h1 :ref="(el) => { heading.element = el }" > This is my page </h1> </div> </template>
Then our script would be written as so, using the el property on our reactive object: const heading = reactive({ el: null }); watchEffect(() => console.log(heading.el)); // "null"
🔥 Watching Nested Values You may not have known this, but you can easily watch nested values directly when using the Options API, just by using quotes: watch: { '$route.query.id'() { // ... } }
This is really useful for working with deeply nested objects! We can also watch nested values using the Composition API: watch( () => value.that.is.really.nested, () => { // ... } );
🎙️ #044 — Our Predictions for Vue and Nuxt in 2025 (with Daniel Roe) After our recap episode on 2024, it is time to look into 2025 - and share our predictions and even some rather spicy hot takes what developers can expect in 2025. Of course, Michael and Alex once again have the Nuxt team Lead Daniel Roe on the show to get some insights on his takes as well! Find out more about their thoughts on Vue Vapor, Nuxt 4, Conferences, Alien Signals, Vue 4, Nitro and many more topics that will be (most likely) relevant in this year. While the focus is mainly Vue and Nuxt, topics around general Web Development are covered too - from AI to Open Source and the job market in 2025. Watch on YouTube or listen on your favorite podcast platform. Chapters: In case you missed them: 📜 How to Use Error Handling to Create Rock-Solid Nuxt Apps Error handling is so important to building robust applications. In this article, we'll go over how to use error handling (all of it!) to create rock-solid Nuxt apps. Check it out here: How to Use Error Handling to Create Rock-Solid Nuxt Apps 📜 12 Design Patterns in Vue Design patterns are incredibly useful in writing code that works well over the long run. They let us use proven solutions to problems that basically every single app has. But there isn't a lot written about how design patterns apply specifically to Vue. In this article, I cover 12 design patterns that I think are crucial to writing great Vue apps. Check it out here: 12 Design Patterns in Vue 📅 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 💬 Simplicity "Complicated code is a sign that you don't understand your program well enough to make it simple." — Steve McConnell 🧠 Spaced-repetition: Reusing Code and Knowledge 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. Don't Repeat Yourself — an acronym that many know but many don't correctly understand. DRY isn't actually about code, it's about the knowledge and decisions that are contained in the code. Too often we are just pattern matching on syntax, and that leads us to bad abstractions that should never exist. Here are some ways we can fix that: - Don't Repeat Yourself (DRY) — Use components and composables to create reusable views and logic. Doing this well is an entire topic all on it's own, which is why I created a whole course on it.
- Optimize for Change — Most of our time is spent modifying existing code, so it pays to make it easy. If code is new or likely to change, don't worry about abstracting it into a new component yet — duplication is welcome here.
- Syntax vs. Knowledge — When removing duplication or "drying up" your code, make sure you're encapsulating knowledge and not syntax. Just because code looks the same doesn't mean it is the same.
🔗 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: |
评论
发表评论