← Back to all snippets
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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs