JAVASCRIPT
Mastering Named and Scoped Slots in Vue 3 Components
Enhance component reusability and flexibility in Vue 3 by leveraging named slots to place content in specific areas and scoped slots for passing data to parent-provided content.
// CardWrapper.vue
<template>
<div class="card">
<header v-if="$slots.header">
<slot name="header"></slot>
</header>
<main>
<slot :cardTitle="title">
<!-- Default content if no slot content is provided -->
<p>Default card content here.</p>
</slot>
</main>
<footer v-if="$slots.footer">
<slot name="footer"></slot>
</footer>
</div>
</template>
<script setup>
import { ref } from 'vue';
const title = ref('My Dynamic Card Title');
</script>
<style scoped>
.card {
border: 1px solid #eee;
border-radius: 8px;
padding: 16px;
margin: 16px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
max-width: 300px;
}
header { border-bottom: 1px solid #eee; padding-bottom: 8px; margin-bottom: 8px; }
footer { border-top: 1px solid #eee; padding-top: 8px; margin-top: 8px; font-size: 0.9em; color: #666; }
</style>
// App.vue
<template>
<CardWrapper>
<template #header>
<h2>Welcome!</h2>
</template>
<template #default="{ cardTitle }">
<p>This is the main content of the card. The child passed: <strong>{{ cardTitle }}</strong></p>
<button>Click Me</button>
</template>
<template #footer>
<p>Last updated: Today</p>
</template>
</CardWrapper>
<CardWrapper /> <!-- Card with default slot content -->
</template>
<script setup>
import CardWrapper from './CardWrapper.vue';
</script>
How it works: This snippet illustrates both named and scoped slots. `CardWrapper.vue` defines a `header` named slot, a `footer` named slot, and a `default` slot. The `default` slot is also a scoped slot, meaning it can pass data (like `cardTitle`) back to the parent component. In `App.vue`, content is provided for these slots using `v-slot` directives (shorthand `#header`, `#default`). The scoped slot data is destructured using `"{ cardTitle }"`, allowing the parent to display dynamic data from the child component, making components highly flexible.