Multiple times I get to know companies that want to improve their productivity when coding in Vue.js.

That’s a too open question, but at least some part can be achieved that by identifying what functionality they build pretty often in their apps, and then having a toolkit of reusable components that allow you to put that common logic in there, while being flexible enough to adapt to other apps.

Vue.js has slots in order to make components have a redefinable structure, but by themselves they’re pretty limited. Sometimes you need some data or state in order to define how a component should render.

If you don’t know slots, I suggest you learn them first on the Vue.js docs.

Scoped slots is an advanced feature in Vue.js that allows you to do that. They’re like normal slots, but they can receive properties as well.

Let’s build a Clock.vue component in order to illustrate that. Basically it must be a time counter:

<template>
  <div class="clock">
    <slot :time="time">
      <p>Default slot</p>
      <p>Time: {{ time.toLocaleTimeString() }}</p>
    </slot>
  </div>
</template>

<script>
  export default {
    data: () => ({
      time: new Date()
    }),
    created() {
      setInterval(() => {
        this.time = new Date(this.time.getTime() + 1000);
      }, 1000);
    }
  };
</script>

You might have noticed the <slot :time="time"> line, that’s the slot receiving the time property. That’s the way this Clock.vue component can send the time data to the component that uses it, while encapsulating the timer logic itself.

You also might have realised that this component already renders the time by itself, as it has some default content within the slot.

But what if we want to redefine what it renders, while holding the timer logic in it?

Well, since we’re passing the time property to the slot, we can do that simply by using the v-slot directive on the root element of the Clock slot. So, wherever you want to render the Clock component, you’ll write something like:

<template>
  <Clock>
    <template v-slot="{ time }">
      <p><b>Slot override!</b></p>
      <p>Date: {{ time.toLocaleDateString() }}</p>
      <p>Time: {{ time.toLocaleTimeString() }}</p>
    </template>
  </Clock>
</template>

v-slot receives all the props passed from within the Clock component. Since that’s JavaScript object, we can use the Object Spread Operator to already grab the time prop as { time }.

Do you see the power of Scoped Slots? You can do more powerful stuff, like render-less components, that you’ll see in a future tip 😜.

If you want to run the code yourself, you can find it in this CodeSandbox!

Remember you can read this tip online (with copy/pasteable code), and don’t forget to share VueDose with your colleagues, so they also know about these tips as well!

See you next week.

Alex

Start saving time and get a tip about the Vue ecosystem every week, right in your inbox.

    Latest Vue Jobs