Vue Slots

Slots are a powerful feature in Vue that allow for more flexible and reusable components.

We use slots in Vue to send content from the parent into the <template> of a child component.

Slots

So far we have just used components inside <template> as self-closing tags like this:

App.vue:

<template>
  <slot-comp />
</template>

Instead, we can use opening and closing tags, and put some content inside, like for example a text:

App.vue:

<template>
  <slot-comp>Hello World!</slot-comp>
</template>

But to receive 'Hello World!' inside the component and display it on our page, we need to use the <slot> tag inside the component. The <slot> tag acts as a placeholder for the content, so that after the application is built the <slot> will be replaced by the content sent to it.

Example

SlotComp.vue:

<template>
  <div>  
    <p>SlotComp.vue</p>
    <slot></slot>
  </div>
</template>
Run Example »

Slots as Cards

Slots can also be used to wrap around larger chunks of dynamic html content to get a card-like appearance.

Earlier we have sent data as props to create content inside compoents, now we can just send the HTML content directly inside the <slot> tag as it is.

Example

App.vue:

<template>
  <h3>Slots in Vue</h3>  
  <p>We create card-like div boxes from the foods array.</p>
  <div id="wrapper">
    <slot-comp v-for="x in foods">
      <img v-bind:src="x.url">
      <h4>{{x.name}}</h4>
      <p>{{x.desc}}</p>
    </slot-comp>
  </div>
</template>

As the content enters the component where the <slot> is, we use a div around the <slot> and style the <div> locally to create a card-like appearance around the content without affecting other divs in our application.

SlotComp.vue:

<template>
  <div> <!-- This div makes the card-like appearance -->
    <slot></slot>
  </div>
</template>

<script></script>

<style scoped>
  div {
    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
    border-radius: 10px;
    margin: 10px;
  }
</style>
Run Example »

Components that produce a card-like frame around content can be reused to create different elements, but with the same card-like frame around.

In this example we use the same component as for the food items to create a footer.

Example

App.vue:

<template>
  <h3>Reusable Slot Cards</h3>
  <p>We create card-like div boxes from the foods array.</p>
  <p>We also create a card-like footer by reusing the same component.</p>
  <div id="wrapper">
    <slot-comp v-for="x in foods">
      <img v-bind:src="x.url">
      <h4>{{x.name}}</h4>
    </slot-comp>
  </div>
  <footer>
    <slot-comp>
      <h4>Footer</h4>
    </slot-comp>
  </footer>
</template>
Run Example »

Fallback Content

If a component is created without content we can have fallback content in the <slot>.

Example

The first component in this application has no content provided, so the fallback content is rendered.

App.vue:

<template>
  <h3>Slots Fallback Content</h3>
  <p>A component without content provided can have fallback content in the slot tag.</p>
  <slot-comp>
    <!-- Empty -->
  </slot-comp>
  <slot-comp>
    <h4>This content is provided from App.vue</h4>
  </slot-comp>
</template>

SlotComp.vue:

<template>
  <div>
    <slot>
      <h4>This is fallback content</h4>
    </slot>
  </div>
</template>
Run Example »

Vue Exercises

Test Yourself With Exercises

Exercise:

When a text is provided between the start tag and end tag of a component like this:

<comp-one>Hello World!</comp-one>

The text provided can be received in the component using slots, like this:

<template>
  <div>  
    <p>CompOne.vue</p>
    
  </div>
</template>

Start the Exercise



Copyright 1999-2023 by Refsnes Data. All Rights Reserved.