Welcome to The Coding College! One of the most powerful features of Vue.js is slots, which allow developers to create highly flexible and reusable components. Slots let you inject content into a child component from the parent, enabling dynamic layouts and robust UI design.
In this guide, we’ll explore the different types of slots, how to use them, and best practices for making the most out of this feature.
What Are Slots in Vue?
Slots provide a way to pass content from a parent component into a child component. This makes components dynamic and reusable by allowing customization of their content without altering their structure or logic.
Basic Slot Usage
Example: Basic Slot
Child Component
File: CardComponent.vue
<template>
<div class="card">
<slot></slot> <!-- Default slot -->
</div>
</template>
<script>
export default {
name: 'CardComponent'
};
</script>
<style scoped>
.card {
border: 1px solid #ddd;
padding: 10px;
border-radius: 5px;
background-color: #f9f9f9;
}
</style>
Parent Component
File: App.vue
<template>
<div>
<CardComponent>
<h1>Welcome to Slots</h1>
<p>This content is passed from the parent component.</p>
</CardComponent>
</div>
</template>
<script>
import CardComponent from './components/CardComponent.vue';
export default {
components: {
CardComponent
}
};
</script>
Rendered Output
<div class="card">
<h1>Welcome to Slots</h1>
<p>This content is passed from the parent component.</p>
</div>
Here, the content inside <CardComponent>
in the parent is injected into the <slot>
in the child component.
Named Slots
Named slots allow you to define multiple slots within a component, each with a unique name.
Example: Named Slots
Child Component
File: CardComponent.vue
<template>
<div class="card">
<header><slot name="header"></slot></header>
<main><slot></slot></main> <!-- Default slot -->
<footer><slot name="footer"></slot></footer>
</div>
</template>
<script>
export default {
name: 'CardComponent'
};
</script>
<style scoped>
.card {
border: 1px solid #ddd;
padding: 10px;
border-radius: 5px;
background-color: #f9f9f9;
}
header, footer {
background-color: #007bff;
color: white;
padding: 5px;
text-align: center;
}
</style>
Parent Component
File: App.vue
<template>
<CardComponent>
<template #header>
<h1>Header Content</h1>
</template>
<p>This is the main content.</p>
<template #footer>
<p>Footer Content</p>
</template>
</CardComponent>
</template>
<script>
import CardComponent from './components/CardComponent.vue';
export default {
components: {
CardComponent
}
};
</script>
Rendered Output
<div class="card">
<header>
<h1>Header Content</h1>
</header>
<main>
<p>This is the main content.</p>
</main>
<footer>
<p>Footer Content</p>
</footer>
</div>
Scoped Slots
Scoped slots allow a child component to pass data back to the parent. This is particularly useful for dynamic content rendering.
Example: Scoped Slots
Child Component
File: ListComponent.vue
<template>
<ul>
<li v-for="item in items" :key="item.id">
<slot :item="item"></slot>
</li>
</ul>
</template>
<script>
export default {
props: {
items: Array
},
name: 'ListComponent'
};
</script>
Parent Component
File: App.vue
<template>
<ListComponent :items="users">
<template #default="{ item }">
<strong>{{ item.name }}</strong> - {{ item.email }}
</template>
</ListComponent>
</template>
<script>
import ListComponent from './components/ListComponent.vue';
export default {
components: {
ListComponent
},
data() {
return {
users: [
{ id: 1, name: 'John Doe', email: '[email protected]' },
{ id: 2, name: 'Jane Smith', email: '[email protected]' }
]
};
}
};
</script>
Rendered Output
<ul>
<li>
<strong>John Doe</strong> - [email protected]
</li>
<li>
<strong>Jane Smith</strong> - [email protected]
</li>
</ul>
Here, the slot
in the child provides access to item
data for each list element, and the parent uses this data to render content dynamically.
Default Slot Content
You can define fallback content inside a <slot>
in case no content is passed from the parent.
Example
<template>
<div class="card">
<slot>This is the default content.</slot>
</div>
</template>
If no content is provided in the parent, the slot will display “This is the default content.”
Best Practices for Using Slots
- Use Named Slots for Clarity: Avoid multiple default slots; use named slots to make the intent clear.
- Document Slot Expectations: Clearly state what kind of data or content should be passed to each slot.
- Limit Scoped Slot Usage: Use scoped slots only when necessary, as they can increase complexity.
- Fallback Content: Always provide default content for better usability.
When to Use Slots
- Flexible Layouts: For components like modals, cards, and lists that require custom content.
- Dynamic Data: Use scoped slots to render data passed from the child to the parent.
- Reusable Components: Create components that can adapt to various use cases with slots.
Conclusion
Slots are an essential feature in Vue for building flexible, reusable, and dynamic components. By mastering basic, named, and scoped slots, you can create components that cater to a wide range of use cases.
For more Vue tutorials and coding insights, visit The Coding College.