A Comprehensive Guide to Vue Slots


A Comprehensive Guide to Vue Slots

Components are the heart of modern web application development. Every app is composed of a number of components smoothly stitched together in order to work as a whole unit. These components need to be maximally flexible and reusable to allow for using them in different situations and even in different apps. One of the main mechanisms many frameworks use to meet such requirements — in partucular Vue — is called a “slot”.

Slots are a powerful and versatile content distribution and composition mechanism. You can think of slots as customizable templates (similar to PHP templates, for example) which you can use in different places, for various use cases, producing different effects. For example, in UI frameworks like Vuetify, slots are used to make generic components such as an alert component. In these kinds of components, slots are used as placeholders for the default content and any additional/optional content, such as icons, images, and so on.

Slots allow you to add any structure, style, and functionality to a particular component. By using slots, developers can drastically reduce the number of props used in a single component, making components much cleaner and manageable.

In this tutorial, we’ll explore how to harness the power of slots in the context of Vue 3. Let’s get started.

Basic Usage of Slots

Basically, Vue offers two kinds of slots: a simple slot, and a scoped slot. Let’s start with the simple one. Consider the following example:

const app = Vue.createApp({})

app.component('primary-button', {
  template: `
    <button>
      <slot>OK</slot>
    </button>`
})

app.mount('#app')

Here, we have a primary button component. We want the button’s text to be customizable, so we use the slot component inside the button element to add a placeholder for the text. We also want a default (fallback) generic value in case we don’t provide a custom one. Vue uses as default slot content everything we put inside the slot component. So we just put the text “OK” inside the component. Now we can use the component like this:

<div id="app">
  <primary-button></primary-button>
</div>

See the Pen
Vue 3 Slots: Basic Slot
by SitePoint (@SitePoint)
on CodePen.

The result is a button with text “OK”, because we haven’t provided any value. But what if we want to create a button with custom text? In that case, we provide custom text in the component implementation like this:

<div id="app">
  <primary-button>Subscribe</primary-button>
</div>

Here, Vue takes the custom “Subscribe” text and uses it instead of the default one.

As you can see, even in this simple example, we get a great amount of flexibility over how we want to present our component. But this is only the tip of the iceberg. Let’s look at a more complex example.

Building a Quote of the Day Component

Now, we’ll build a quote component which displays the quote of the day. Here’s the code:

const app = Vue.createApp({}) 

app.component('quote', {
  template: `
    <article>
      <h2>The quote of the day says:</h2>
      <p class="quote-text">
        <slot></slot>
      </p>
    </article>`
})

app.mount('#app')
<div id="app">
  <quote>
    <div class="quote-box">
      "Creativity is just connecting things."
      <br><br>
      - Steve Jobs
    </div>
  </quote>
</div>
.quote-box {
  background-color: lightgreen;
  width: 300px;
  padding: 5px 10px;
}

.quote-text {
  font-style: italic;
}

In this example, we create a title heading whose content will be constant, and then we put a slot component inside a paragraph, whose content will vary depending on the current day’s quote. When the component is rendered, Vue will display the title from the quote component followed by the content we put inside the quote tags. Also pay attention to the CSS classes used both in the quote creation and implementation. We can style our components in both ways depending on our needs.

See the Pen
Vue 3 Slots: Quote Component
by SitePoint (@SitePoint)
on CodePen.

Our quote of the day component works fine, but we still need to update the quote manually. Let’s make it dynamic by using the Fav Quotes API:

const app = Vue.createApp({   
  data() {
    return {
      quoteOfTheDay: null,
      show: false
    };
  },
  methods: {
    showQuote() {
      axios.get('https://favqs.com/api/qotd').then(result => {
        this.quoteOfTheDay = result.data
        this.show = true
      }); 
    }
  }
})

...

app.mount('#app')
<div id="app">
  <quote>
    <button v-if="show == false" @click="showQuote">Show Quote of the Day</button>
    <div v-if="show" class="quote-box">
      {{ quoteOfTheDay.quote.body }} 
      <br><br>
      - {{ quoteOfTheDay.quote.author }}
    </div>
  </quote>
</div>

Here, we use Axios to make a call to the “Quote of the Day” API endpoint, and then we use the body and author properties, from the returned JSON object, to populate the quote. So we no longer need to add the quote manually; it’s done automatically for us.

See the Pen
Vue 3 Slots: Quote Component with Axios
by SitePoint (@SitePoint)
on CodePen.

Using Multiple Slots

Although a single slot can be quite powerful, in many cases this won’t be enough. In a real-world scenario, we’ll often need more than one single slot to do the job. Fortunately, Vue allows us to use as many slots as we need. Let’s see how we can use multiple slots by building a simple card component.

Building a Basic Card Component

We’ll build a card component with three sections: a header, a body, and a footer:

const app = Vue.createApp({})

app.component('card', {
  template: `
    <div class="container">
      <header>
        <slot name="header"></slot>
      </header>
      <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </div>`
})

app.mount('#app')
<div id="app">
  <card>
    <template v-slot:header>
      <h2>Card Header Title</h2>
    </template>

    <template v-slot:default>
      <p>
        Lorem ipsum leo risus, porta ac consectetur ac, vestibulum at eros. Donec id elit non mi porta gravida at eget metus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras mattis consectetur purus sit amet fermentum.
      </p>
    </template>

    <template v-slot:footer>
      <a href="#">Save</a> -
      <a href="#">Edit</a> -
      <a href="#">Delete</a>
    </template>
  </card>
</div>

In order to use multiple slots, we must provide a name for each of them. The only exception is the default slot. So, in the above example, we add a name property for the header and footer slots. The slot with no name provided is considered default.

When we use the card component, we need to use the template element with the v-slot directive with the slot name: v-slot:[slot-name].

See the Pen
Vue 3 Slots: Card Component
by SitePoint (@SitePoint)
on CodePen.

Note: the v-slot directive has a shorthand, which uses special symbol # followed by the slot’s name. So, for example, instead of v-slot:header, we can write #header.

Named slots can also be used with third-party components, as we’ll see in the next section.

Using Named Slots with Bulma’s Card Component

Let’s take the Bulma’s Card component and tweak it a little bit:

const app = Vue.createApp({})

app.component('card', {
  template: `
    <div class="container">
      <div class="card">
        <header class="card-header">
          <slot name="header"></slot>
        </header>
        <main class="card-content">
          <slot></slot>
        </main>
        <footer class="card-footer">
          <slot name="footer"></slot>
        </footer>
      </div>
    </div>`
})

app.mount('#app')
.container {
  width: 300px;
}
<div id="app">
  <card>
    <template v-slot:header>
      <p class="card-header-title">
        Card Header Title
      </p>
    </template>

    <template v-slot:default>
      <p>
        Lorem ipsum leo risus, porta ac consectetur ac, vestibulum at eros. Donec id elit non mi porta gravida at eget metus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras mattis consectetur purus sit amet fermentum.
      </p>
    </template>

    <template v-slot:footer>
      <a href="#" class="card-footer-item">Save</a>
      <a href="#" class="card-footer-item">Edit</a>
      <a href="#" class="card-footer-item">Delete</a>
    </template>
  </card>
</div>

Here, we use the classes from the Bulma Card component as a base skeleton and add a slot for each section (header, content, footer). Then, when we add the content, everything is structured properly.

See the Pen
Vue 3 Slots: Card Component with Bulma
by SitePoint (@SitePoint)
on CodePen.

Continue reading
A Comprehensive Guide to Vue Slots
on SitePoint.

This article was republished from its original source.
Call Us: 1(800)730-2416

Pixeldust is a 20-year-old web development agency specializing in Drupal and WordPress and working with clients all over the country. With our best in class capabilities, we work with small businesses and fortune 500 companies alike. Give us a call at 1(800)730-2416 and let’s talk about your project.

FREE Drupal SEO Audit

Test your site below to see which issues need to be fixed. We will fix them and optimize your Drupal site 100% for Google and Bing. (Allow 30-60 seconds to gather data.)

Powered by

A Comprehensive Guide to Vue Slots

On-Site Drupal SEO Master Setup

We make sure your site is 100% optimized (and stays that way) for the best SEO results.

With Pixeldust On-site (or On-page) SEO we make changes to your site’s structure and performance to make it easier for search engines to see and understand your site’s content. Search engines use algorithms to rank sites by degrees of relevance. Our on-site optimization ensures your site is configured to provide information in a way that meets Google and Bing standards for optimal indexing.

This service includes:

  • Pathauto install and configuration for SEO-friendly URLs.
  • Meta Tags install and configuration with dynamic tokens for meta titles and descriptions for all content types.
  • Install and fix all issues on the SEO checklist module.
  • Install and configure XML sitemap module and submit sitemaps.
  • Install and configure Google Analytics Module.
  • Install and configure Yoast.
  • Install and configure the Advanced Aggregation module to improve performance by minifying and merging CSS and JS.
  • Install and configure Schema.org Metatag.
  • Configure robots.txt.
  • Google Search Console setup snd configuration.
  • Find & Fix H1 tags.
  • Find and fix duplicate/missing meta descriptions.
  • Find and fix duplicate title tags.
  • Improve title, meta tags, and site descriptions.
  • Optimize images for better search engine optimization. Automate where possible.
  • Find and fix the missing alt and title tag for all images. Automate where possible.
  • The project takes 1 week to complete.