JAVASCRIPT
Creating Flexible Components with Dynamic Slot Names
Master dynamic slots in Vue 3 to build highly configurable and reusable components, allowing parent components to inject content into specific named slots conditionally.
// BaseCard.vue
<template>
<div class="card">
<header class="card-header">
<!-- Default slot for header, or named 'header' -->
<slot name="header">
<h2>Default Header</h2>
</slot>
</header>
<div class="card-body">
<!-- Default slot for body content -->
<slot></slot>
</div>
<footer class="card-footer">
<!-- Dynamic slot name passed via prop -->
<slot :name="footerSlotName">
<p>Default Footer Content</p>
</slot>
</footer>
</div>
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
footerSlotName: {
type: String,
default: 'footer' // Default to a standard 'footer' slot
}
});
</script>
<style scoped>
.card {
border: 1px solid #eee;
border-radius: 8px;
padding: 16px;
margin: 16px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
max-width: 300px;
}
.card-header, .card-footer {
padding: 8px 0;
border-bottom: 1px solid #eee;
margin-bottom: 8px;
}
.card-footer {
border-top: 1px solid #eee;
border-bottom: none;
margin-top: 8px;
}
</style>
// --- In a parent component (e.g., App.vue) ---
<template>
<div>
<h1>Dynamic Slots Example</h1>
<!-- Card with default slots and specific named header -->
<BaseCard>
<template #header>
<h3>Custom Card Title</h3>
</template>
<p>This is the main content of the card.</p>
</BaseCard>
<!-- Card using a dynamic slot name for the footer -->
<BaseCard footerSlotName="actionButtons">
<template #actionButtons>
<button>Learn More</button>
<button>Dismiss</button>
</template>
<p>This card has custom action buttons in the footer.</p>
</BaseCard>
</div>
</template>
<script setup>
import BaseCard from './BaseCard.vue';
</script>
How it works: Vue 3's dynamic slots allow a child component to define a slot whose name is determined by a prop or reactive state. This provides immense flexibility, enabling parent components to inject content into different named slots based on conditions or configuration passed to the child. In the example, `BaseCard` uses a prop `footerSlotName` to dynamically render content into a slot, allowing the parent `App.vue` to decide which content goes into the footer area by passing a specific slot name.