Exclusive tips every week

Join 11,067 other Vue devs and get exclusive tips and insights delivered straight to your inbox, every week.

    Picture of Michael Thiessen

    👋Hey friend! I work hard to send you amazing stuff each week.

    — Michael

    I really love and enjoy reading these emails.

    You are one of the most pro VueJS devs I know, and I am happy that you share this knowledge.

    Fabian Beer

    Here's my latest newsletter

    🔥 (#131) Contextually Aware Quiz Components

    Hey!

    This week I've got some extra content for you, from the Clean Components Toolkit (in addition to your regular weekly dose of tips).

    I've been working hard on adding tools to solve how we organize logic in our apps.

    It's not enough to know how to split components up. We also need to know how to simplify and organize the logic within those components effectively.

    Luckily, the Composition API opens up a whole lot of possibilities for us!

    But don't worry, if you're still using the Options API, there are ways to incrementally opt-in that aren't too painful (we covered this last week).

    Have an awesome week!

    — Michael

    Contextually Aware Quiz Components

    I recorded a short video to go through how I implemented the quiz functionality in the Clean Components Toolkit.

    Here, I use one of my favourite patterns, Contextually Aware Components.

    They're sort of magical ✨ and that's why I love them.

    https://vimeo.com/866392131

    🔥 Extract Conditional Pattern (Bonus Tip)

    This is one of my favourite tools from the Clean Components Toolkit.

    It's super easy to implement, and can be applied in so many situations to clean up your code fairly quickly.

    We can apply this in almost any place we have a v-if in our component.

    When we extract each branch body we go from this:

    <div v-if="condition">
    <div>
    <!-- Lots of code here -->
    </div>
    </div>
    <div v-else>
    <div>
    <!-- Lots of other code -->
    </div>
    </div>

    To this:

    <div v-if="condition">
    <NewComponent />
    </div>
    <div v-else>
    <OtherComponent />
    </div>

    We know we can do this for two reasons:

    1. Each branch is semantically related
    2. Each branch does distinct work

    We know that each branch is semantically related, meaning all of that code works together to perform the same task.

    Each branch also does distinct work — otherwise, why have a v-if at all?

    This means it's a perfect opportunity to create new components.

    And by replacing a large chunk of code with a well-named component that represents the code’s intent, we make our code much more self-documenting.

    However, this pattern doesn't always work well. If we have a lot of branches we may want to switch to using the Strategy Pattern, another tool included in the Clean Components Toolkit.

    🔥 Prose Components in Nuxt 3

    With Nuxt Content 2 we can customize how Markdown gets rendered in our Nuxt 3 apps by creating our own custom Prose components.

    We do get code highlighting built-in through Shiki, but I already have a custom theme for Prism.

    So I needed to create a custom ProseCode component that used PrismJS to render the code blocks from my Markdown:

    <template>
    <pre :class="`language-${language}`"
    ><code v-html="highlighted"></code></pre>
    </template>
    import Prism from 'prismjs';
    const props = withDefaults(
    defineProps<{
    code?: string;
    language?: string | null;
    filename?: string | null;
    highlights?: Array<number>;
    }>(),
    {
    code: '',
    language: null,
    filename: null,
    highlights: [],
    }
    );
    const highlighted = props.language
    ? Prism.highlight(
    props.code,
    Prism.languages[props.language],
    props.language
    )
    : props.code;

    When we place this component in ~components/content and name it ProseCode, Nuxt Content knows to use it when rendering code blocks from Markdown.

    We get a few props, and then use PrismJS to highlight it. This is all done on the server too, so our code is already highlighted before it hits the client.

    Note: the formatting inside of the pre tag looks weird because it will preserve any formatting, including newlines. Moving the code element to the next line and indenting would cause the code rendered to the page to also have an extra newline and a few spaces in front of it.

    You can create custom Prose components for most elements.

    🔥 toRef default value

    You've been using toRef for a while, but did you know you can also supply a default value?

    const bank = reactive({
    Rand: 3400,
    Egwene: 20,
    Matrim: 230340,
    Padan: -20340,
    })
    // toRef(object, property, default)
    const myBankAccount = toRef(bank, 'Michael', 1000 * 1000);

    Probably the easiest way to become a millionaire.

    🔥 Don't set height and width

    Setting the height (or width) explicitly on an element is a code smell for me, whether you're using px or percentages or any other units.

    Why do I not like it?

    Because there's almost always a better way, and the height property usually makes things more difficult. It also messes with how the flexbox and grid layout systems work.

    Instead, it's better to rely on the natural size of the content, padding, borders, and margin.

    Of course, there are some caveats where I do like using height and width:

    • Filling space using 100% or 100vh
    • Making specific shapes, like a circle that has a height and width of 50px (you'll see this all over my site)

    I'm more likely to set min-height or max-height to create more responsive designs.

    📜 Client-Side Error Handling in Nuxt 3

    It may not be as fun as shipping the next feature, but making sure our apps are rock-solid and can recover from errors is crucial.

    Without good error-handling, our UX suffers and our applications can be hard to use.

    In this article I explore handling client-side errors using the NuxtErrorBoundary component.

    Check it out here: Client-Side Error Handling in Nuxt 3

    💬 It always takes longer

    "It always takes longer than you expect, even when you take into account Hofstadter's Law." — Hofstadter's Law

    🧠 Spaced-repetition: Reusability Fundamentals: The Configuration Pattern

    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.

    So you've got a fantastic CodeBlock component that does syntax highlighting and even shows line numbers:

    <CodeBlock language="js">
    const myMessage = 'Highlighting code is supa ez';
    </CodeBlock>

    But now, you need to support a second colour theme.

    Instead of copy and pasting (which is sometimes the right solution!), we can use props to help us create variations:

    <!-- Uhhh, maybe not the best solution -->
    <DarkModeCodeBlock language="js">
    const myMessage = 'Highlighting code is supa ez';
    </DarkModeCodeBlock>
    <!-- This is what props were meant for -->
    <CodeBlock
    language="js"
    theme="darkMode"
    >
    const myMessage = 'Highlighting code is supa ez';
    </CodeBlock>

    You already do this intuitively, so this may not be a huge revelation.

    But the Configuration pattern is a fundamental pattern — you can't ignore it if you want to master reusability.

    Dealing with prop explosions and understanding the Base Component Pattern is also part of mastering Configuration, the second level of reusability.

    And the other, more exciting levels of reusability?

    Well, mastering Configuration is vital to unlocking them. All the other levels build on top of this one.



    p.s. I also have four products to help you learn Vue: Clean Components Toolkit, Vue Tips Collection, Mastering Nuxt 3 and Reusable Components

    Here's what others are saying

    I'm starting to think that your newsletter is one of the best things that happened to me this year. I just love these emails.
    Stanislaw Gregor
    I'm somewhere in the upper-middle level at Vue, and I never miss an email you and always find something cool when reading!
    Eduard Climov
    This is the first time where I'm actually enjoying email newsletters. I like your format a lot.
    Fahmi Alfituri
    You have great content in your emails. I seriously learn something from every one of them.
    Titus Decali
    Just wanted to say I enjoy these emails. They encourage me to constantly improve my craft. Fantastic work.
    Joe Radman
    Thanks for another beautiful tip 🙏
    Victor Martins Onuoha
    Loving these, and the spaced repetition.
    Mark Goldstein
    I really enjoy reading your emails, because I love Vue. Thanks for these emails.
    Arturo Espinoza
    I really love and enjoy reading these emails. You are one of the most pro VueJS devs I know, and I am happy that you share this knowledge.
    Fabian Beer
    THANK YOU! I did not know about the deep property, so I assumed you simply couldn't watch objects.
    Darryl Noakes
    I really must say you are doing a really great job. Now I am aware of a cleaner and more performant way to use Tailwind. Thanks a lot!
    Henry Eze
    Thank you so much, I really enjoy and appreciate your emails.
    Carlos Gonzalez
    Thanks for sharing great Vue tips.
    Fernando Navarro
    I really enjoy these tips.
    Martin H
    Thank you so much for the weekly Vue education. Thanks and live on longer to educate us more.
    Kabolobari Benakole
    I look forward to your emails every week. This week was something I knew, but I like to be reminded of. Thanks for keeping it up!
    Nathan Strutz
    Thank you for your weekly emails. I always look forward to learning a new tip about Vue or at least relearning old tips :)
    Colin Johnson
    I have really been enjoying your weekly emails, and I also got my two team members to join in on the fun as well.
    Keith Dawson
    Thank you for your newsletter, your explanations have very concise examples and I like it.
    Nicolas Decayeux
    Thanks A LOT for your great work!!! One of the few newsletters that I let pass!
    Martin Tillmann

    Want to level up your Vue skills?

    With over two million reads and 11,067 subscribers, you've come to the right place.

    Subscribe now to get exclusive insights and tips every week.