DEV Community

Cover image for Vue. Slots. First touch
Ilya N. Zykin
Ilya N. Zykin

Posted on

Vue. Slots. First touch

First time I met using slots in Vue.js

I wanted to figure out how it works, because I could not develop tests without a deep understanding of this concept.

Let's see how it works

components/MyComponent.vue

<script setup>
const greetingMessage = 'hello';
const someNumber = 123;
</script>

<template>
  <div>
    <slot name="header" :text="greetingMessage" :count="someNumber"></slot>
    <slot :text="greetingMessage" :count="someNumber"></slot>
    <slot name="footer" :text="greetingMessage" :count="someNumber"></slot>
  </div>
</template>

Enter fullscreen mode Exit fullscreen mode

App.vue

<script setup lang="ts">
import MyComponent from './components/MyComponent.vue';
</script>

<template>
  <MyComponent>
    <template #header="headerProps">
      <p>HEADER: {{ headerProps }}</p>
    </template>

    <template #default="defaultProps">
      <p>DEFAULT: {{ defaultProps }}</p>
    </template>

    <template #footer="{ text, count }">
      <p>FOOTER: {{ text }} = {{ count }}</p>
    </template>
  </MyComponent>
</template>
Enter fullscreen mode Exit fullscreen mode

Slots inside Components

  • By default a slot works as a { children } parameter in React components. It provides a way to take a content of a Component (<MyComponent>CONTENT HERE</MyComponent>) and place it inside internals of the component.
  • In a component Slot reserves a place where a content will be placed, if the content comes from the parent level.
  • A component may have multiple slots inside
  • Slot without a name, by default has name default

Slots outside Components

  • WOW! From the inside of the component slots may pass data on the level of parent.

<slot name="header" :text="hello">

passes the text variable to template (to the upper level)

<template #header="headerProps">

now inside <template #header> you can use

{{ headerProps.text }}

  • WOW! Ordering of slots inside a component defines an order outside, and affects on ordering of templates.

Even if here we have an order: header, default, footer

  <MyComponent>
    <template #header="headerProps">
      <p>HEADER: {{ headerProps }}</p>
    </template>

    <template #default="defaultProps">
      <p>DEFAULT: {{ defaultProps }}</p>
    </template>

    <template #footer="{ text, count }">
      <p>FOOTER: {{ text }} = {{ count }}</p>
    </template>
  </MyComponent>
Enter fullscreen mode Exit fullscreen mode

but if we define the order of slots like that footer, header, default:

    <slot name="footer" :text="greetingMessage" :count="someNumber"></slot>
    <slot name="header" :text="greetingMessage" :count="someNumber"></slot>
    <slot :text="greetingMessage" :count="someNumber"></slot>
Enter fullscreen mode Exit fullscreen mode

Then it will produce the result

FOOTER: hello = 123

HEADER: { "text": "hello", "count": 123 }

DEFAULT: { "text": "hello", "count": 123 }
Enter fullscreen mode Exit fullscreen mode

It was pretty unexpected to me.

Playground

Happy Coding!

Top comments (0)