🔥 (225) Start with the Interface, Flexible Arguments, and Shorthand for Named Slots

​ ​

Read this on my blog

We just released the final videos of Mastering Nuxt: Full Stack Unleashed!

This last chapter covers authentication with Nuxt Auth Utils. We cover session management, protecting both server routes and client routes, seeding data when a user logs in, and more.

It's the best way to learn Nuxt, and is up-to-date with Nuxt 4. You can read more about what that means in this article:

Master Nuxt 4 from Day One: No Waiting, No Outdated Content

Since the course is now complete, the early access period will be ending soon. So grab your copy for a great price before the price goes up!

Mastering Nuxt: Full Stack Unleashed

— Michael

Nuxt Tips Collection

Master Nuxt without hours digging through docs. Learn what you need in just 5 minutes a day:

  • 117 practical tips to unlock hidden features of Nuxt
  • 14 chapters covering components, routing, SSR, testing and more
  • 3 daily tips for 3 months via email
  • 7 real-world code repos to learn from
  • Reviewed by Nuxt core team for accuracy
"Highly recommend Michael's Nuxt Tips Collection. He's one of the best Vue & Nuxt teachers I know." — Sébastien Chopin

Master Nuxt Today →

🔥 Start with the Interface

When writing a composable, don't immediately dive into implementing it.

Instead, take a moment to figure out how you will be using the component. Take some time to think about the interface between the composable and the rest of your app.

A few minutes upfront can save you a lot of tears and frustration later on.

Here are a few questions you may want to ask yourself before starting:

  • What arguments should the composable receive?
  • What options do we want to include?
  • What does the composable return?
  • Do we want to use dynamic return values here?
  • What does the minimum useful version look like, and how quickly can we get there?
  • What does the final version look like? Is there anything easy we can do now to prepare for that?

Of course, your composable will change and evolve over time.

But it's much easier to start off heading in the right direction.

🔥 Flexible Arguments

Sometimes we have a ref that we want to use with our composable. Sometimes we just have the raw data.

Wouldn't it be nice if it didn't matter what we already had? Then we could use our composables and it would just work?

Here's an example using the useTitle composable from VueUse:

// We have a ref already  const titleRef = ref('This is the title of the page');  useTitle(titleRef);    // We just have the string  const title = 'This is the title of the page';  const titleRef = useTitle(title);

We can do this by implementing the Flexible Arguments pattern:

export function useTitle(maybeRef) {    const titleRef = ref(maybeRef);    	// Use titleRef in the composable  }

The ref function will either create a ref for us, or return a ref if we give it one.

This means that we can pass it either type and we know we'll get a ref back.

The opposite is true with the unref function. If we need to use a raw primitive value rather than a ref in our composable, we can use unref to achieve a similar result.

export function useTitle(maybeRef) {    const titleString = unref(maybeRef);    	// Use titleString in the composable  }

If you want more patterns on writing better composables, check out my course: Composable Design Patterns.

🔥 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>

We can write this:

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

📜 Make Your Components Easier to Think About

I hate thinking.

Well, actually, I love thinking, but only when I'm able to solve problems or make progress with it.

But often our code gets in the way of this. And as one workshop attendee said about reading code, "if you're confused, it's not your fault."

This article goes over some ways you can make your code easier to think about, so you're less confused and can actually get stuff done.

Check it out here: Make Your Components Easier to Think About

📜 Exploring Server Components in Nuxt

You may have heard about server components, but there are some really interesting things you can do with them.

In this article I explore a few really cool things we can do with server components.

Check it out here: Exploring Server Components in Nuxt

💬 Programmers and designers

"If you make a general statement, a programmer says, 'Yes, but...'while a designer says, 'Yes, and...'." — André Bensoussan

🧠 Spaced-repetition: How to Watch Props for Changes

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.

With the Composition API, we have several great options for watching props.

The recommended approach would be using either watch or watchEffect in your script setup:

import { watch, watchEffect } from "vue";  const props = defineProps<{ count: number }>();  watch(    () => props.count,    (val) => {      console.log(val);    }  );  watchEffect(    () => console.log(props.count)  );

Script Setup + Composition API

When using the watch method, we have to provide a getter function instead of passing the value directly. This is because the prop object itself is reactive, but the individual props are not.

You can test this for yourself by passing in the reactive prop object directly:

watch(    props,    (val) => {      console.log(val);    }  );

The difference between watch and watchEffect is that watch requires us to specify exactly what we're watching, while watchEffect will simply watch every value that is used inside of the method that we pass to it.

So we have a tradeoff between simplicity and flexibility.

Composition API + Options API

If you're using the setup() function within the Options API, the only difference is in how we specify the props. Otherwise, everything else works exactly the same:

import { watch, watchEffect } from "vue";    export default {    props: {      count: {        type: Number,        required: true,      },    },    setup(props) {      watch(        () => props.count,        (val) => {          console.log(val);        }      );        watchEffect(() => console.log(props.count));    },  };

Options API

The process is straightforward with the Options API.

Just use the name of the prop as the name of the watcher, and you're good to go!

export default {    props: {      count: {        type: Number,        required: true,      },    },    watch: {      count(val) {        console.log(val);      },    },  };

Although this syntax is simpler than the Composition API syntax, the tradeoff is that there is far less flexibility.

If you want to watch multiple things at once, or have any fine-grained control over the dependencies, the Composition API is much easier to use.

🔗 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:

Unsubscribe

评论

此博客中的热门博文

Weekly Vue News #141 - Share Styling Using Wrapper Components

Scripting News: Tuesday, October 8, 2024

Scripting News: Tuesday, August 20, 2024