Nwose Lotanna Web Developer and Writer

Using Vue.js slots to pass HTML content to components

5 min read 1413

Editor’s note: This post was last updated on 9 September 2021 to improve code, images, and any outdated information.

This post will show you how to pass data from a parent component child components in Vue.js using Vue slots.

Before you start

This post is suited for developers of all stages — including beginners — though there are some prerequisites to acknowledge before going through this tutorial.

You will need the following on your machine:

  • Node.js version 14.x and above installed
  • A code editor; I highly recommend Visual Studio Code
  • Vue’s latest version, installed globally on your machine
  • Vue CLI 4.x installed on your machine; uninstall the old CLI version first if needed
  • Download and install a Vue starter project here

What are slots in Vue.js?

Vue slots are Vue template elements created by the Vue team to provide a platform for template content distribution. It is an implementation of the a content distribution API that was inspired by the Web Components spec draft.

Using Vue slots, you can pass or distribute HTML code across various components in your project.

What is the purpose of slots in Vue.js?

Content distribution is important for many reasons, some of which have to do with structure. With Vue slots, you can structure an HTML interface (like with TypeScript), which you can then use as a guide to build out your components by template injection.

It is a very scalable and efficient solution for passing down template code from one component to another.

Positioning content is another great use case for Vue slots. You can just create a template and then use another component or the parent component to arrange that template as you want it to appear in the user interface.

Slots vs. props

If you know about Vue slots, you might wonder if props and slots do the same thing. Well, the central idea of these tools or platforms is to encourage reusability and efficiency of resources. With that in mind, slots and props are similar.

We made a custom demo for .
No really. Click here to check it out.

Props deal with passing data objects from component to component, but slots deal with passing template (HTML) content instead from component to component. However, scoped slots act exactly like props; this will be clearly illustrated in this tutorial.

Vue.js slot syntax

For slots, your child component acts as the interface or structure of how you want your content arranged. It can look like this:

<template>
  <div>
    <slot></slot>
  </div>
</template>

The parent component (where the HTML content to be injected into the child component resides) can look like this:

<Test>
   <h2>Hello World!</h2>
 </Test>

This combination returns a user interface that looks like this:

<template>
  <div>
    <h2>Hello World!</h2>
  </div>
</template>

Notice how the slot on its own serves as a guide for where and how content will be injected — that is the central idea.

Using Vue.js slots to pass HTML content with components

If you have followed this post from the start, you will have the Vue starter project open in Visual Studio Code. To illustrate the simple example in the syntax section, our parent component will be the app.vue file. Open your app.vue file and copy in this code block:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <Test>
      <h2>Hello World!</h2>
    </Test>
  </div>
</template>
<script>
import Test from './components/Test.vue'
export default {
  name: 'app',
  components: {
    Test
  }
}
</script>

The child component is the test component, so copy the code block below in the test.vue file:

<template>
  <div>
    <slot></slot>
  </div>
</template>
<script>
export default {
  name: 'Test'
}
</script>

Run the application in the dev environment with this command:

npm run serve

It then renders the following:

Using Slots To Render Vue Logo And "Hello World"

How do you use Vue.js named slots?

Vue allows for more than one slot for a component, which means that you can have any number of slots you want. To test this out, copy this new code block into your test.vue file:

<template>
  <div>
    <slot></slot>
    <slot></slot>
    <slot></slot>
  </div>
</template>
<script>
export default {
  name: 'Test'
}
</script>

If you run the application, you can see that hello world is printed three times. So if you want to add more content — say, a header, a paragraph with text, and then an unordered list — Vue lets us name the scopes so that it can identify the particular scope to display.

Naming the slots in the test.vue file look like this:

<template>
  <div>
    <slot name="header"></slot>
    <slot name="paragraph"></slot>
    <slot name="links"></slot>
  </div>
</template>
<script>
export default {
  name: 'Test'
}
</script>

Now, you must also label the HTML elements according to the slot name to display them in. Copy this into the template section of your app.vue file:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <Test>
      <h2 slot="header">Hello world!</h2>
      <p slot="paragraph">Hello, I am a paragraph text</p>
      <ul slot="links">
        <li>Hello, I am a list item</li>
        <li>Hello, I am a list item</li>
      </ul>
    </Test>
  </div>
</template>

How do you use V-slots?

When Vue version 2.6 was released, it shipped with a better syntax to reference slot names from child components called v-slot, which is meant to replace the initial slot syntax. So, instead of a parent component template with slots like this:

<Test>
   <h1 slot="header">Hello world!</h1>
</Test>

From version 3.0, it now looks like this:

<Test v-slot:header>
   <h1>Hello world!</h1>
</Test>

Notice that aside from the minor change in the string from slot to v-slot, there is also a major change: the v-slot can only be defined on templates instead of on any HTML element. This is a big change as it questions the usability of named slots, but as of this writing, slots are still very much part of the documentation.

What are scoped slots?

Imagine a scenario in which the Vue slot can also access a data object in the child component from the parent component — a kind of slot with props capability.

To illustrate this, go ahead and create a data object in the child component by copying the code block below into the test.vue file:

<template>
  <div>
    <slot v-bind:team="team"></slot>
    <slot name="paragraph"></slot>
    <slot name="links"></slot>
  </div>
</template>
<script>
export default {
  name: 'Test',
  data(){
    return{
      team:"FC Barcelona"
    }
  }
}
</script>

Just like normal props, the v-bind directive binds the team in the data with the prop reference in the parent component. Open your app.vue file and copy the code block below into the template section:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <Test v-slot="{team}">
      <h2>Hello world! my team is {{team}}</h2>
    </Test>
  </div>
</template>

If you run your application, you see that the data object was successfully passed to the parent component. You can find the complete code for this tutorial here.

Using Scoped Slots To Render Vue Logo

Conclusion

This post introduced you to slots in Vue.js and how they are important to content injection. You saw how to set it up, and even how to have more than one slot for a component. You also saw how slots can act as props by scoping. Go ahead and enjoy implementing slots in your workflow.

Experience your Vue apps exactly how a user does

Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.

Modernize how you debug your Vue apps - .

Nwose Lotanna Web Developer and Writer

Leave a Reply