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 »