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.
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.
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>
:
<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:
<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.
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:
<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 ChildComponent
s - one with slot content and one without:
<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.
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
:
<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:
<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.
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.
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!