JAVASCRIPT
Creating Flexible Components with Default and Named Slots
Learn how to build highly reusable Vue 3 components using both default and named slots, allowing parent components to inject dynamic content.
// BaseCard.vue
<template>
<div class="card">
<header v-if="$slots.header" class="card-header">
<slot name="header"></slot>
</header>
<div class="card-body">
<slot></slot> <!-- Default slot -->
</div>
<footer v-if="$slots.footer" class="card-footer">
<slot name="footer"></slot>
</footer>
</div>
</template>
<style scoped>
.card {
border: 1px solid #ddd;
border-radius: 8px;
margin: 10px;
padding: 15px;
width: 300px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.card-header {
font-weight: bold;
margin-bottom: 10px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
.card-footer {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid #eee;
font-size: 0.9em;
color: #666;
}
</style>
// App.vue (Parent Component)
<template>
<BaseCard>
<!-- Content for the default slot -->
<p>This is the main content of the card.</p>
<!-- Content for the named header slot -->
<template #header>
<h2>Welcome Card</h2>
</template>
<!-- Content for the named footer slot -->
<template #footer>
<small>Posted on 2023-10-27</small>
</template>
</BaseCard>
<BaseCard>
<template #header>
<h3>Another Card Example</h3>
</template>
<p>This card has different content and only a header, demonstrating slot optionality.</p>
</BaseCard>
</template>
<script setup>
import BaseCard from './components/BaseCard.vue';
</script>
How it works: This snippet illustrates how to create a highly flexible `BaseCard` component using both a default slot and named slots (`header`, `footer`). The parent `App.vue` component can then inject specific content into these slots, customizing the card's appearance and functionality without modifying the `BaseCard`'s internal structure. The `$slots` object is used to conditionally render parts of the component only if content is provided for a specific slot, enhancing reusability.