Tutorial

How To Use Component Slots in Vue.js

Updated on March 4, 2021
author

Joshua Bemenderfer

How To Use Component Slots in Vue.js

Introduction

Oftentimes you will need to allow your parent Vue components to embed arbitrary content inside of child components. Vue provides a way to accomplish this with slots.

Note: If you are coming from an Angular background, this is a similar concept to transclusion or content projection.

In this tutorial, you will explore an example Vue project with a parent component and child component that shares content with slots.

Prerequisites

If you would like to follow along with this article, you will need:

This tutorial was verified with Node v15.10.0, npm v7.6.0, and vue v2.6.11.

Using Slots

To allow a parent component to pass DOM elements into a child component, provide a <slot> element inside the child component.

Here is an example of a ChildComponent that contains a <slot>:

ChildComponent.vue
<template>
  <div>
    <p>This is the child component.</p>
    <slot></slot>
  </div>
</template>

Here is an example of a ParentComponent that populates the ChildComponent with content:

ParentComponent.vue
<template>
  <div>
    <p>This is the parent component.</p>
    <ChildComponent>
      <p>This is injected content from the parent component.</p>
      <p>It can still bind to data in the parent's scope: {{myVariable}}</p>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      myVariable: `Parent Variable`
    }
  }
}
</script>

Viewing the application in a web browser will produce the following result:

Output
<div> <p>This is the parent component.</p> <div> <p>This is the child component.</p> <p>This is injected content from the parent component.</p> <p>It can still bind to data in the parent's scope: Parent Variable</p> <div> </div>

Content and data from the parent component are injected into the child component.

Providing Fallback Content

If the parent component does not inject any content into the child component’s <slot>, the child component will render any elements inside its <slot> tag:

Here is an example of a ChildComponent with fallback content:

ChildComponent.vue
<template>
  <div>
    <p>This is the child component.</p>
    <slot>
      <p>Fallback Content</p>
    </slot>
  </div>
</template>

Here is an example of a ParentComponent that has two ChildComponents - one with slot content and one without:

ParentComponent.vue
<template>
  <div>
    <p>This is the parent component with slot data.</p>
    <ChildComponent>
      <p>Slot Content</p>
    </ChildComponent>
    <p>This is the parent component without slot data.</p>
    <ChildCmponent></ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
}
</script>

Viewing the application in a web browser will produce the following result:

Output
<div> <p>This is the parent component with slot data.</p> <div> <p>This is the child component.</p> <p>Slot Content</p> <div> <p>This is the parent component without slot data.</p> <div> <p>This is the child component.</p> <p>Fallback Content</p> <div> </div>

Fallback content appears when slot content is not provided by the parent component.

Note: If there is no <slot> element in the child component <template>, any content from the parent component will be silently discarded.

This completes a brief introduction into using <slot> and fallbacks.

Using Named Slots

Having one <slot> element to inject content can satisfy some use cases. However, you may have other use cases where you want to utilize multiple <slot> elements. It is possible to achieve this with Vue with named slots.

Named slots are <slot> elements with a name attribute to allow for namespaced content injection:

<slot name="slotName"></slot>

Consider an example component that features named slots for main and aside:

ChildComponent.vue
<template>
  <div>
    <main>
      <slot name="main"></slot>
    </main>
    <aside>
      <slot name="aside"></slot>
    </aside>
    <slot></slot>
  </div>
</template>

The parent component populates the main and aside slots. Content that does not reference a named slot populates the empty slot:

ParentComponent.vue
<template>
  <div>
    <ChildComponent>
      <template v-slot:main>
        <p>Custom Main</p>
      </template>
      <template v-slot:aside>
        <p>Custom Aside</p>
      </template>
      <div>
        <p>Custom Content</p>
      </div>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
}
</script>

Note: Prior to Vue 2.6.0, you would have used slot attributes. It has since been replaced with the v-slot directive. Vue 3 will deprecate and eventually remove slot attributes.

Viewing the application in a web browser will produce the following result:

Output
<div> <div> <main> <p>Custom Main</p> </main> <aside> <p>Custom Aside</p> </aside> <p>Custom Errata</p> <div> </div>

This completes a brief introduction into using named slots.

Conclusion

In this tutorial, you explored a Vue project with a parent component and child component example that shares content with slots.

If you’d like to learn more about Vue.js, check out our Vue.js topic page for exercises and programming projects.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Joshua Bemenderfer

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.