Vue Slots
Pass content from parent to child components flexibly
🎰 What are Slots?
Slots allow you to pass content from a parent component into a child component's template. They make components reusable by letting you customize content while keeping the structure consistent and organized.
<!-- Parent -->
<Card>
<h2>My Title</h2>
<p>My content</p>
</Card>
<!-- Child (Card.vue) -->
<div class="card">
<slot></slot>
</div>
Slot Features
Content Distribution
Pass any content to components
<Modal>
<p>Any content</p>
</Modal>
Reusability
Same component, different content
<Button>Save</Button>
<Button>Cancel</Button>
Flexibility
Customize component internals
<Card>
<img src="..." />
<h3>Title</h3>
</Card>
Default Content
Fallback when no content passed
<slot>
Default text
</slot>
🔹 Basic Slot Usage
Create a simple component with a slot:
🔸 Child Component (AlertBox.vue)
<template>
<div class="alert">
<strong>Alert:</strong>
<slot></slot>
</div>
</template>
<style scoped>
.alert {
padding: 15px;
background: #fff3cd;
border: 1px solid #ffc107;
border-radius: 4px;
}
</style>
🔸 Parent Component Usage
<template>
<div>
<AlertBox>
This is a warning message!
</AlertBox>
<AlertBox>
<p>Another alert with HTML</p>
</AlertBox>
</div>
</template>
Output:
Another alert with HTML
🔹 Default Slot Content
Provide fallback content when no content is passed:
<!-- Child Component (Button.vue) -->
<template>
<button class="btn">
<slot>Click Me</slot>
</button>
</template>
<!-- Parent Usage -->
<template>
<div>
<!-- Uses default content -->
<Button />
<!-- Custom content -->
<Button>Submit</Button>
</div>
</template>
Output:
🔹 Named Slots
Use multiple slots with different names:
<!-- Child Component (Card.vue) -->
<template>
<div class="card">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
<!-- Parent Usage -->
<template>
<Card>
<template #header>
<h2>Card Title</h2>
</template>
<p>Main content goes here</p>
<template #footer>
<button>Action</button>
</template>
</Card>
</template>
🔹 Slot with Dynamic Content
Pass dynamic data through slots:
<template>
<div>
<Panel>
<h3>{{ title }}</h3>
<p>{{ description }}</p>
</Panel>
</div>
</template>
<script setup>
import { ref } from 'vue'
import Panel from './Panel.vue'
const title = ref('Dynamic Title')
const description = ref('This content is dynamic!')
</script>
🔹 Conditional Slot Rendering
Check if slot content exists before rendering:
<template>
<div class="container">
<header v-if="$slots.header">
<slot name="header"></slot>
</header>
<main>
<slot>No content provided</slot>
</main>
<footer v-if="$slots.footer">
<slot name="footer"></slot>
</footer>
</div>
</template>
Tip: Use $slots to check if a slot has content before rendering wrapper elements.