Exclusive tips every week

If you like Anthony's newsletter on Vue.js Developers, you'll enjoy this one, too.

Join 13,567+ 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

    🔥 (241) Configurable composables, named slots, and looping over a range

    Hey there!

    I hope you're having a fantastic week.

    Here are some tips and other Vue content for you.

    — Michael

    🔥 Configurable Composables

    We can make our composables more reusable by passing in an object that contains all of the configuration options for how we want the composable to behave:

    const state = ref({ email: '' });
    const { history, undo, redo } = useRefHistory(state, {
    // Track history recursively
    deep: true,
    // Limit how many changes we save
    capacity: 10,
    });

    We use an object here instead of a long list of parameters:

    const { history, undo, redo } = useRefHistory(state, true, 10));

    Using an options object instead of parameters gives us several benefits.

    First, it’s self-documenting. We have the name of the parameter right beside the value, so we never forget what each value is doing.

    We can also create a type for the entire options object:

    export type RefHistoryOptions {
    deep?: boolean;
    capacity?: number;
    };
    export type RefHistoryReturn {
    history: Ref;
    undo: () => void;
    redo: () => void;
    };
    export function useRefHistory(
    ref: Ref,
    options: RefHistoryOptions
    ): RefHistoryReturn {};

    Second, we don’t need to worry about ordering or unused options. The more potential edge cases we cover with a composable, the more options we’ll have. But we usually only need to worry about a couple of them at one time — they’re all optional.

    Third, it’s much easier to add new options. Because the order doesn’t matter and none of the options are required, adding a new capability to our composable won’t break anything. We simply add it to the list of possible options and carry on.

    The pattern doesn’t require a lot of work to implement, either:

    export function useRefHistory(ref, options) {
    const {
    deep = false,
    capacity = Infinity,
    } = options;
    // ...
    };

    First, we pass in the options object as the last parameter. This makes it possible to have the options object itself as an optional parameter.

    The required params come first. Typically, there will only be one or two. More parameters is a code smell, and likely means that your composable is trying to do too much.

    The required parameter (or parameters) is very often a Ref, or a MaybeRef if we’re also implementing the Flexible Arguments Pattern.

    We then access the options by destructuring.

    Doing this gives us a really clean and readable way of providing defaults. Remember, these are options so they should all have defaults. If the values are required they should likely have

    This helps to clarify what options are being used in this composable. It’s not uncommon for one composable to use another composable, and in that case some of the options are simply passed along to the inner composable:

    export function useRefHistory(ref, options) {
    const {
    deep = false,
    capacity = Infinity,
    ...otherOptions,
    } = options;
    // Pass along some options we're not using directly
    useSomeOtherComposable(otherOptions);
    };

    🔥 Multiple Named Slots

    Named slots allow you to design components with multiple content insertion points, each identified by a unique name.

    This is particularly useful when a single slot isn't sufficient for the component's complexity.

    For example, an Input component might need to display icons before or after the input field:

    <!-- Input.vue -->
    <template>
    <div class="input-styling">
    <slot name="icon-before" />
    <input ...>
    <slot name="icon-after" />
    </div>
    </template>

    Using the component, you can choose where to place an icon by targeting the specific named slot:

    <template>
    <Input>
    <template #icon-before>
    <IconBefore />
    </template>
    </Input>
    <Input>
    <template #icon-after>
    <IconAfter />
    </template>
    </Input>
    </template>

    Named slots can be applied in any order and are referenced directly under the component they belong to.

    They can also be dynamically generated, offering even more flexibility.

    🔥 Looping Over a Range in Vue

    The v-for directive allows us to loop over an Array, but it also let's us loop over a range:

    <template>
    <ul>
    <li v-for="n in 5">Item #{{ n }}</li>
    </ul>
    </template>

    This will render out:

    • Item #1
    • Item #2
    • Item #3
    • Item #4
    • Item #5

    When we use v-for with a range, it will start at 1 and end on the specified number.

    📜 Composition API vs. Options API

    The Composition API and Options API are two different ways to structure your Vue code.

    In this article I compare the two in depth, and give my own opinion on which one is best (it's the Composition API).

    Check it out here: Composition API vs. Options API

    📜 24 Time-Saving Tips for Nuxt

    We know that Nuxt is a fantastic tool.

    But it has so many amazing features that it’s hard to keep track of them all.

    That’s why I’ve compiled this giant list of 24 Nuxt tips for you — use them to save time and write better Nuxt apps.

    We cover a lot of topics here, including:

    • When to use /assets vs. /public directory
    • Using runtimeConfig vs. app.config
    • Understanding how Universal rendering works (and how it’s different from SPA and SSR)
    • A utility to make your own NuxtLink components that no one is talking about
    • Adding a basic cache to your data fetching — since Nuxt doesn’t do this by default

    Of course, there is so much more!

    Check it out here: 24 Time-Saving Tips for Nuxt

    💬 Things

    "Things aren’t always #000000 and #FFFFFF." — undefined

    🧠 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.

    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:

    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.