Unleashing the Power of Slots in Vue.js
Tags: webdev, vue, beginners, javascript
Published: 2023-02-06 10:11:08

Vue.js is a popular JavaScript framework used for building user interfaces. One important aspect of Vue.js is understanding how to use slots. With the recent release of [Vue 3](https://vuejs.org/guide/introduction.html), the syntax for using slots has been made more succinct. 

This change to slots has gotten me re-interested in discovering the potential power of slots to provide reusability, and clearer readability to our Vue-based projects.

With Vue slots, you can turn a part or all of your components into reusable templates that will render differently based on different use cases. All you need to do is embed them in slots.
In this article, I’ll help you understand the concept of Vue slots and show you how to use them.


## What are slots

Slots in Vue.js are a powerful feature that allows components to be reused and display dynamic content. Slots allow you to pass content into a component and define how it is displayed. This can make your code more modular and reusable, allowing you to create complex applications with ease. Slots are the Vue equivalent to [transclusion in Angular](https://docs.angularjs.org/api/ng/directive/ngTransclude) and [child props in React](https://reactjs.org/docs/composition-vs-inheritance.html).


## Types of slots

In Vue.js, there are basically two types of slots:

- Default slots
- Named slots.


## Overview of slots

We understand the whole concept from the definition of slots —  it’s about making components reusable. The best way to understand them is to see them in action. Let’s start with a simple example:

```javascript
// example.vue
<template>
  <div class="example">
    <slot></slot>
  </div>
</template>
```
The component above has a wrapper `div`. Let’s assume that `div` is there to create a stylistic frame around its content. This component is able to be used generically to wrap a frame around any content you want. Let’s see what it looks like to use it. 

```javascript
// app.vue
<template>
  <example><img src="logo.png"></example>
</template>
```

The content that is between the opening and closing example tags will get inserted into the example component where the slot is, replacing the slot tags. This is the most basic way of doing it. It will look like this: 

![example-image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3kahx6i85aqf1li5zals.png)

You can also specify default content to go into a slot simply by filling it in:

```php
// example.vue
<template>
  <div class="example">
    <slot>This is the default content if nothing gets specified to go here</slot>
  </div>
</template>
```

So now if we use it like this instead:

```php
// app.vue
<template>
  <example />
</template>
```

The default text of “This is the default content if nothing gets specified to go here” will show up, but if we use it as we did before, the default text will be overridden by the `img` tag:


![example-image2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9x8wut24szkf5xvk84bd.png)


## Default slots

Default slots are a way to pass content from the parent component to a child component. The content passed to a default slot is rendered inside the child component, allowing the parent component to customize the content of the child component.

A default slot is defined in the child component template using the <slot> element without a `name` attribute. When using a default slot, the content passed from the parent component is placed directly inside the child component, replacing the <slot> element.

For example, consider a **Card** component that contains a `header`, `main content` area, and `footer`:

```javascript
//Mycard.vue
    <template>
  <div class="card">
    <header class="card-header">
      <slot name="header"></slot>
    </header>
    <main class="card-main">
      <slot></slot>
    </main>
    <footer class="card-footer">
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

<style>
  .card {
    border: 1px solid lightgray;
    border-radius: 5px;
    box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1);
    width: 300px;
    height: 200px;
    display: flex;
    flex-direction: column;
  }

  .card-header,
  .card-footer {
    background-color: lightgray;
    padding: 1rem;
    text-align: center;
  }

  .card-main {
    flex-grow: 1;
    background-color: lightyellow;
    padding: 1rem;
  }
</style>

```
This component creates a card with a header, main content area, and footer. The default slot is defined in the `main` section, where the content passed from the parent component will be rendered.

To pass content to the default slot, the parent component uses the child component in its template, placing the content directly inside:

```javascript
//app.vue
    <template>
  <MyCard>
    Main Content
  </MyCard>
</template>

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

export default {
  components: {
    MyCard,
  },
};
</script>
```
The content `Main Content` will be rendered in the main section of the `Card` component as shown below:

![Default-slot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dyiczxa3gc0clm8fsm1f.png)




### Named Slots

The best way to organize a slot-based component system is to name your slots. Named slots are a way to pass content from the parent component to a child component, similar to default slots. However, named slots allow the parent component to specifically target and customize different parts of the child component.

A named slot is defined in the child component template using the `<slot>` element with a name attribute. The name attribute specifies the name of the slot and is used by the parent component to target and customize that specific part of the child component.

For example, consider a component called **`MyLayout`**:

```javascript
//MyLayout.vue
   <template>
  <div class="layout">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

<style>
  .layout {
    display: flex;
    flex-direction: column;
    height: 100vh;
  }

  header,
  footer {
    background-color: lightgray;
    padding: 1rem;
  }

  main {
    flex-grow: 1;
    background-color: lightyellow;
    padding: 1rem;
  }
</style>

```

This component creates a layout with a `header`, `main content` area, and `footer`. The named slots are defined in the header and footer sections, where the content passed from the parent component will be rendered.

To pass content to a named slot, the parent component uses the child component in its template and specifies the name of the slot using the `v-slot` directive:

```javascript
//app.vue
<template>
  <MyLayout>
    <template v-slot:header>
      <h1>Header</h1>
    </template>
    <p>Main Content</p>
    <template v-slot:footer>
      <h1>Footer</h1>
    </template>
  </MyLayout>
</template>

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

export default {
  components: {
    MyLayout,
  },
};
</script>

```
The content **Header** will be rendered in the header section of **MyLayout** component, and the content **Footer** will be rendered in the footer section. The content **Main Content** will be rendered in the default slot, which is located in the main section just like below:

![Named-slot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1e8mp2eqyvrnijmxse6x.png)



## Reusability with slots

Props are a great way to reuse components, but they have their limitations depending on your use case. Props tend to work best in components that have the same format and content, but just different values.

Sometimes you need to make your components a little more flexible and adaptable: maybe you want some components to have certain sections while depending on the page it’s on, you want to remove other sections.
By injecting your content using slots, it makes it easier to switch around the content of a component without having to worry about using template logic to handle rendering.



## Conclusion

While Vue slots are a pretty simple concept, it’s super powerful in designing amazing components. We have seen the different ways to reuse properties of a component by using the slot property. This takes component-based development to a whole new level, and while I’ve demonstrated a lot of great ways slots can be used, there are countless more out there. Feel free to explore them.

You can read more about [Vue slots](https://vuejs.org/guide/components/slots.html) on Vue’s official site.