Read this on my blog Hey all! This is a quieter week for me. I'm mostly heads down working on the big update and re-recording of Mastering Nuxt to bring it all up to date. The code is nearly there, just a little bit of polishing left to make it fantastic. — Michael 🔥 Nesting Reactive Objects Here's a nuance to nesting reactive objects that's tripped me up. Nesting a ref in a reactive array keeps everything reactive as expected: const arr = reactive([]); arr.push(ref('hello')); arr.push(ref('world')); setTimeout(() => (arr[0].value = 'nothing'), 1000);
But putting this ref inside a non-reactive object breaks this reactivity: const arr = reactive([]); arr.push({ text: ref('hello'), }); arr.push({ text: ref('world'), }); setTimeout(() => (arr[0].value = 'nothing'), 1000);
I gave a hint in that last sentence — this is because it's being wrapped in a non-reactive object. The trail of reactivity goes cold once we hit this object, but only because we're accessing the text property through the non-reactive object. If we instead access the ref directly, we're able to trigger a reactive update as expected: const arr = reactive([]); const one = ref('hello'); const two = ref('world'); arr.push({ text: one, }); arr.push({ text: two, }); // This triggers the update correctly setTimeout(() => (one.value = 'nothing'), 1000);
Of course, this isn't about refs in particular. All we need is to keep the reactivity alive, which we can also achieve using reactive . 🔥 A bunch of composable mini tips Yes, mini tips within a tip. It's meta. Here they are: - Start with the end in mind, and write the return first. Once you know how you want the composable to be used, filling in the implementation details is much easier.
- Use an options object as the parameter. This makes it easy to add new parameters in the future without breaking anything, and you won't mess up the ordering anymore.
- Keep them small. Embrace the UNIX philosophy and make sure each composable only does one thing but does it well.
- Name them consistently:
use , create , on_ - Always make sure your reactivity is hooked up before any async logic. By using a
ref of null , you can update those values later when your logic completes. No need to await around. - Use
effectScope to group effects if you have lots of them in your composable. This makes cleaning up your reactivity a lot simpler. If you have large objects, use shallowRef instead to prevent Vue from recursively making the whole thing reactive. Of course, you'll need to use triggerRef to trigger any reactive effects for it, but it can improve performance. Some tips on making your composables more flexible: - If you're using a
watch , make immediate and flush configurable - Accept both
refs and primitive values as inputs. By passing the variable through ref , you'll either reuse the existing ref or create a new one. - The same trick works with
unref if what you need in your composable is a primitive and not a ref . 🔥 Shorthand for named slots Named slots also have a shorthand syntax, one that's much nicer to look at. Instead of writing this: <DataTable> <template v-slot:header> <TableHeader /> </template> </DataTable>
<DataTable> <template #header> <TableHeader /> </template> </DataTable>
Not a huge difference, but a little cleaner for sure. I think the # character is easier to pick out than v-slot when reading code. 🎙️ #045 — FormKit and Hot Takes (with Justin Schroeder) Together with the FormKit author Justin Schroeder, Michael and Alex discuss the challenges of building forms on the internet. While it seems like a simple task, forms can be complex and pretty time-consuming. Especially when it is more than a Newsletter or Contact Form. Justin shares his experience building FormKit (multiple times), a form library for Vue.js, and how it can help developers build forms faster and more efficiently. From Accessibility to actually covering edge cases such as form hydration and repopulation! Of course, we couldn't let Justin go without talking about some of his hot takes from Vue in 2024, over to Vapor Mode, and Tailwind. Watch on YouTube or listen on your favorite podcast platform. Chapters: In case you missed them: 📜 Quick Pinia Overview (video) This video from LearnVue shows you the most essential bits of Pinia. Pinia is the official state management library for Vue 3, so it's definitely worth taking some time to understand it! Check it out here: Quick Pinia Overview (video) 📜 3 Kinds of Props in Vue One of Vue's core features is the use of props. Props are how we pass data around in Vue, from parent to child components. But not all props are created equal. There are three main kinds: - Template Props
- Configuration Props
- State Props (or Data Props).
Check it out here: 3 Kinds of Props in Vue 📅 Upcoming Events Here are some upcoming events you might be interested in. Let me know if I've missed any! 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 💬 One way street "A good programmer is someone who always looks both ways before crossing a one-way street." — Doug Linder 🧠 Spaced-repetition: Global Properties 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. It's possible to add global properties to your Vue app in both Vue 2 and Vue 3: // Vue 3 const app = createApp({}); app.config.globalProperties.$myGlobal = 'globalpropertiesftw'; // Vue 2 Vue.prototype.$myGlobal = 'globalpropertiesftw';
I would recommend prefixing any global properties with a $ . This helps prevent naming conflicts with other variables, and it's a standard convention that makes it easy to spot when a value is global. This global property can be accessed directly off of any component when using the Options API: computed: { getGlobalProperty() { return this.$myGlobal; }, },
Why can't this be used with the composition API? Because the composition API is designed to be context-free and has no access to this . Instead, you can create a simple composable to access your globals: <script setup> import useGlobals from './useGlobals'; const { $myGlobal } = useGlobals(); </script>
// useGlobals.js export default () => ({ $myGlobal: 'globalpropertiesftw', });
🔗 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: |
评论
发表评论