🔥 Vue Tips #30: Reusability Fundamentals: The Configuration Pattern

Michael Thiessen - Oct 19 '21 - - Dev Community

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

Hey there,

I'm still trying to adjust to the darkness this time of year in Canada.

It's dark when I start work at 8, and dark again when I finish around 5. I work in my basement, so I don't get a lot of light during the day either.

So I'm trying to take some time during the day to get outside and get some sunlight (and fresh air).

Do you change your working habits throughout the year? A different schedule during winter or summer?

— Michael

🔥 How I deal with dynamic classes

A pattern I use constantly is triggering classes with boolean flags:

<template>
  <div :class="disabled && 'disabled-component'">
    Sometimes this component is disabled. Other times it isn't.
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode
/* Some styles */
.disabled-component {
  background-color: gray;
  color: darkgray;
  cursor: not-allowed;
}
Enter fullscreen mode Exit fullscreen mode

Either the trigger is a prop I use directly, or a computed prop that tests for a specific condition:

disabled() {
  return this.isDisabled || this.isLoading;
}
Enter fullscreen mode Exit fullscreen mode

If I just need one class on an element, I use the logical AND to trigger it:

<div :class="disabled && 'disabled-component'"></div>
Enter fullscreen mode Exit fullscreen mode

Sometimes it's a decision between two classes, so I'll use a ternary:

<div
  :class="disabled ? 'disabled-component' : 'not-yet-disabled'"
/>
Enter fullscreen mode Exit fullscreen mode

I don't often use more than two classes like this, but that's where an Object or Array comes in handy:

<div
  :class="{
    primary: isPrimary,
    secondary: isSecondary,
    tertiary: isTertiary,
  }"
/>
Enter fullscreen mode Exit fullscreen mode
<div
  :class="[
    isPrimary && 'primary',
    isSecondary && 'secondary',
    isTertiary && 'tertiary',
  ]"
/>
Enter fullscreen mode Exit fullscreen mode

Of course, when it gets complex enough it's better to just have a computed prop that returns a string of class names (or returns an Object or Array):

<div :class="computedClasses" />
Enter fullscreen mode Exit fullscreen mode

🔥 Reusability Fundamentals: The Configuration Pattern

So you've got an awesome CodeBlock component that does syntax highlighting, and even shows line numbers:

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

But now you need to support a second color 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>
Enter fullscreen mode Exit fullscreen mode
<!-- This is what props were meant for -->
<CodeBlock
  language="js"
  theme="darkMode"
>
  const myMessage = 'Highlighting code is supa ez';
</CodeBlock>
Enter fullscreen mode Exit fullscreen mode

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 are also part of mastering Configuration, the second level of reusability.

And the other, more interesting levels of reusability?

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

📜 Using Vue for a VS Code extension?

This is a very interesting article on creating your own VS Code extension...

But you get to build the UI using Vue.

It goes into all the steps necessary to set up and get your extension running. From there, the sky is the limit (unless you're building rockets 🚀).

Read it now: Building a VS Code Extension Using Vue.js

🗞 Nuxt 3! Yeah, it's here!

It was officially released yesterday, and comes with some amazing stuff:

  • Vue 3
  • Vite
  • Typescript
  • and so many other features

Check it out here.

Also, don't forget that Vue.js London is happening next week!

💬 Repeated failure

As a rule, software systems do not work well until they have been used, and have failed repeatedly, in real applications. — Dave Parnas

I think Dave is talking about edge cases.

You think you've covered them all, but you never have. Not until real users start using it for real.

🧠 Spaced-repetition: Reducing Objects

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.

The reduce function is really great for converting arrays into objects, but it can be intimidating.

If we have a bunch of items that all have an id:

{
  id,
  //...
}
Enter fullscreen mode Exit fullscreen mode

We can reorganize the array into an object, where the key for each item is the item's id:

const obj = arr.reduce((prev, next) => {
  // Grab the id from the item
  const { id } = next;

  // Add the item to our object
  prev[id] = next;

  // Return the object so we can add more items
  return prev;
}, {});
Enter fullscreen mode Exit fullscreen mode

You get an object that looks like this:

{
  'id1': { id: 'id1', ... },
  'id2': { id: 'id2', ... },
  'id3': { id: 'id3', ... },
}
Enter fullscreen mode Exit fullscreen mode

If you want to group all objects in an array by a specific property, you can do something very similar:

const obj = arr.reduce((prev, next) => {
  // Grab the property from the item that we want to group by
  const { prop } = next;

  // Add a new array to the object if this is the first one
  // with this value
  if (prev[prop] === undefined) {
    prev[prop] = [];
  }

  // Add our item to this array
  prev[prop].push(next);

  // Return the object so we can add more items
  return prev;
}, {});
Enter fullscreen mode Exit fullscreen mode

Our final object looks like this:

{
  'prop1': [
    { prop: 'prop1', ... },
    { prop: 'prop1', ... },
    { prop: 'prop1', ... },
  ],
  'prop2': [
    { prop: 'prop2', ... },
    { prop: 'prop2', ... },
    { prop: 'prop2', ... },
  ],
}
Enter fullscreen mode Exit fullscreen mode

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

. . . . . . . . . . . . . . .