DEV Community

Michael Thiessen
Michael Thiessen

Posted on • Originally published at michaelnthiessen.com

🔥 Vue Tips #31: The limitations of props

This newsletter was sent out to my list on October 20, 2021. Sign up here to get emails like this each week!

As always, here are some tips.

Enjoy.

— Michael

🔥 Static and dynamic classes

We can add static and dynamic classes to an element at the same time:

<ul>
  <li
    v-for="item in list"
    :key="item.id"
    class="always-here"
    :class="item.selected && 'selected'"
  >
    {{ item.name }}
  </li>
</ul>
Enter fullscreen mode Exit fullscreen mode

This lets you apply basic styling through static classes, and then dynamically add other styles as you need them.

You can also achieve the same thing when using an Object or Array with dynamic classes:

<ul>
  <li
    v-for="item in list"
    :key="item.id"
    :class="{
      'always-here': true,
      selected: item.selected,
    }"
  >
    {{ item.name }}
  </li>
</ul>
Enter fullscreen mode Exit fullscreen mode

Or with an Array:

<ul>
  <li
    v-for="item in list"
    :key="item.id"
    :class="[
      'always-here',
      item.selected && 'selected',
    ]"
  >
    {{ item.name }}
  </li>
</ul>
Enter fullscreen mode Exit fullscreen mode

I prefer splitting them out into class and :class bindings though, since it makes the code clearer. It also makes it less likely to be broken when refactored!

🔥 The limitations of props

Props are useful, but they have two glaring issues:

  1. Impossible to pass markup*
  2. Not that flexible

*not technically impossible, but not something you want to do.

The solution to these two problems is the same, but we'll get there in a second.

Many components you create are contentless components. They provide a container, and you have to supply the content. Think of a button, a menu, an accordion, or a card component:

<Card title="Shrimp Tempura">
  <img src="picOfShrimp.jpg" />
  <div>
    <p>Here are some words about tempura.</p>
    <p>How can you go wrong with fried food?</p>
  </div>
  <a href="www.michaelnthiessen.com/shrimp-tempura">
    Read more about Shrimp Tempura
  </a>
</Card>
Enter fullscreen mode Exit fullscreen mode

You can often pass this content in as a regular String. But many times you want to pass in a whole chunk of HTML, maybe even a component or two.

You can't do that with props.*

*again, yes, you could do this, but you'll definitely regret it.

Props also require that you plan for all future use cases of the component. If your Button component only has two values for type, you can't just use a third without modifying the Button:

<!-- You just have to believe it will work -->
<Button type="AWESOME" />
Enter fullscreen mode Exit fullscreen mode
// Button.vue
export default {
  props: {
    type: {
      type: String,
      // Unfortunately, 'AWESOME' doesn't work here :/
      validator: val => ['primary', 'secondary'].includes(val),
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

I'm not a psychic, and I'm guessing you aren't either.

The solution to these problems?

I think I gave it away with my card example above...

..slots! 🎰

Slots allow you to pass in whatever markup and components you want, and they also are fairly open-ended, giving you lots of flexibility. This is why in many cases, slots are simply better than props.

📜 A photoshop plugin with Vue!?

Last week I shared an article on creating a VS Code extension.

Now we break out of the web world entirely, and see how we can create a plugin for Photoshop.

I had no idea this was even possible!

Read it now: Make Your First Plugin with Vue JS for Photoshop and Adobe XD

🗞 Vue.js London is today + tomorrow!

Quick, don't miss out on some amazing talks at Vue.js Conference (London) — happening right now!

Conferences are an amazing place to learn and connect with other Vue devs.

We're slowly starting to see some more in-person events, along with lots of virtual ones too.

Here are some upcoming conferences:

(Let me know if I've missed any.)

💬 Brute force

When in doubt, use brute force. — Steve McConnell

I'm often just not clever enough to come up with a clever solution.

But cleverness isn't the point of software development.

It's developing software that works.

🧠 Spaced-repetition: 6 Levels of Reusability

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.

My course on reusable components covers this framework, which outlines six different levels of reusability that you can use in your components.

Here are the six levels of reusability:

  1. Templating — Reusing code by wrapping it up inside of a component
  2. Configuration — Using configuration props to allow for varying behaviour
  3. Adaptability — Allowing components to become future-proof
  4. Inversion — Letting other components control the process
  5. Extension — Using reusability throughout our component
  6. Nesting — Creating powerful hierarchies of components

I cover this in more detail in this excerpt from the course

Exclusive tips and insights every week

Join 8335 other Vue devs and get exclusive tips and insights like these delivered straight to your inbox, every week.

You have great content in your emails. I seriously learn something from every one of them. — Titus Decali

Thanks for another beautiful tip 🙏 — Victor Onuoha

Loving these, and the spaced repetition — Mark Goldstein

Sign up here

Discussion (0)