JAVASCRIPT
Implement Flexible Components with Named and Scoped Slots
Master Vue 3 slots, including named and scoped slots, to create highly reusable and configurable components that accept dynamic content from parent components.
// components/CardComponent.vue
<template>
<div class="card">
<header v-if="$slots.header">
<slot name="header"></slot>
</header>
<main>
<slot :cardData="dataFromCard">
<!-- Default content if no slot content is provided -->
<p>Default card content goes here.</p>
</slot>
</main>
<footer v-if="$slots.footer">
<slot name="footer"></slot>
</footer>
</div>
</template>
<script setup>
import { ref } from 'vue';
const dataFromCard = ref('Hello from Card Component!');
</script>
<style scoped>
.card {
border: 1px solid #ccc;
padding: 15px;
margin: 10px;
border-radius: 8px;
}
.card header { border-bottom: 1px solid #eee; padding-bottom: 10px; margin-bottom: 10px; }
.card footer { border-top: 1px solid #eee; padding-top: 10px; margin-top: 10px; }
</style>
// App.vue
<template>
<CardComponent>
<!-- Named Slot for Header -->
<template #header>
<h2>My Custom Card Header</h2>
</template>
<!-- Default (unnamed) Slot with Scoped Props -->
<template v-slot="slotProps">
<p>{{ slotProps.cardData }}</p>
<p>This is dynamic content provided to the main slot.</p>
</template>
<!-- Named Slot for Footer -->
<template #footer>
<button>Learn More</button>
</template>
</CardComponent>
<CardComponent>
<!-- No header, no footer, just default main content -->
</CardComponent>
</template>
<script setup>
import CardComponent from './components/CardComponent.vue';
</script>
How it works: This snippet illustrates how to use named and scoped slots in Vue 3. `CardComponent` defines a `header` slot, a default (unnamed) slot that passes `cardData` as a prop (scoped slot), and a `footer` slot. `App.vue` then demonstrates how to inject custom content into these slots, utilizing the `v-slot` directive (or its shorthand `#`) and accessing scoped slot props, making components highly reusable and customizable.