Join 13,567+ other Vue devs and get exclusive tips and insights delivered straight to your inbox, every week.

πHey friend! I work hard to send you amazing stuff each week.
βΒ Michael
Hey!
Happy New Year's Eve! It's been an amazing year for Vue and Nuxt. Wishing you all the best for 2026.
Let's close out the year with some tips and articles.
β Michael
Context-aware components are "magical" β they adapt to what's going on around them automatically, handling edge cases, state sharing, and more.
There are 3 main types of context-aware components, but configuration is the one I find most interesting.
When you break up a large component into smaller ones, they often still need to share state.
Instead of pushing that work on whoever's consuming the components, you can make this happen "behind the scenes."
To give you more flexibility, you may break up a Dropdown component into Select and Option components. But to make it easier to use, the Select and Option components share the selected state with each other:
<!-- Used as a single component for simplicity --><Dropdown v-model="selected" :options="[]" /><!-- Split up for more flexibility --><Select v-model="selected"><Option value="mustard">Mustard</Option><Option value="ketchup">Ketchup</Option><div class="relish-wrapper"><Option value="relish">Relish</Option></div></Select>
Sometimes component behaviour needs to change based on what's going on in the rest of the application. This is often done to automagically handle edge cases that would otherwise be annoying to deal with.
A Popup or Tooltip should reposition itself so it doesn't overflow out of the page. But if that component is inside a modal, it should move, so it doesn't overflow out of the modal.
This can be done automagically if the Tooltip knows when it's inside a modal.
You already create context-aware CSS, applying different styles based on what's happening in parent or sibling elements.
.statistic {color: black;font-size: 24px;font-weight: bold;}/* Give some separation between statsthat are right beside each other */.statistic + .statistic {margin-left: 10px;}
CSS variables let us push this further, allowing us to set different values in different parts of the page.
For your unit tests, @nuxt/test-utils lets you opt-in to a Nuxt environment by adding .nuxt. to the filename of your test:
./tests/MyComponent.nuxt.test.ts
You can also add a special comment at the top of the file:
@vitest-environment nuxt
Or enable the environment for all Vitest tests in your config:
// vitest.config.tsimport { defineVitestConfig } from '@nuxt/test-utils/config';export default defineVitestConfig({test: {environment: 'nuxt'},};
When testing, you'll often need to shallow render a componentΒ β mocking out any descendent components to keep your test simpler.
With @nuxt/test-utils you can use the mockComponent utility method to help with that:
import { mockComponent } from '@nuxt/test-utils/runtime';// Use Options API to configuremockComponent('MyComponent', {props: {value: String},setup(props) {// ...},});// Or use a separate file to clean things up (and use <script setup>)mockComponent('MyComponent', () => import('./MyComponent.mock.vue'));// ...tests
In this video from LearnVue, we see how easy it can be to add a powerful drag and drop system in to your app.
Check it out here: Adding Drag and Drop (video)
Learn how to write bulletproof watchers in Vue, when to use onCleanup and onWatcherCleanup, and how to build reusable cleanup helpers.
Check it out here: Bulletproof Watchers in Vue
"Automating chaos just gives faster chaos." βΒ Mark Fewster
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.
You can use reactive to make the switch from the Options API a little easier:
// Options APIexport default {data() {username: 'Michael',access: 'superuser',favouriteColour: 'blue',},methods: {updateUsername(username) {this.username = username;},}};
We can get this working using the Composition API by copying and pasting everything over using reactive:
// Composition APIsetup() {// Copy from data()const state = reactive({username: 'Michael',access: 'superuser',favouriteColour: 'blue',});// Copy from methodsupdateUsername(username) {state.username = username;}// Use toRefs so we can access values directlyreturn {updateUsername,...toRefs(state),}}
We also need to make sure we change this β state when accessing reactive values, and remove it entirely if we need to access updateUsername.
Now that itβs working, itβs much easier to continue refactoring using ref if you want to β or just stick with reactive.
Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links.
p.s. I also have a bunch of products/courses: