JAVASCRIPT

Creating Flexible Layout Components with Vue 3 Scoped Slots

Master Vue 3 scoped slots to build highly reusable components that let parent components define how specific parts of the child's content are rendered, passing data back.

// CardComponent.vue
<template>
  <div class="card">
    <div class="card-header">
      <slot name="header" :title="headerTitle">Default Header</slot>
    </div>
    <div class="card-body">
      <slot :contentData="bodyContent">Default Body Content</slot>
    </div>
    <div class="card-footer">
      <slot name="footer">Default Footer</slot>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
const headerTitle = ref('My Awesome Card');
const bodyContent = ref('This is the main content of the card.');
</script>

<style scoped>
.card { border: 1px solid #ccc; padding: 10px; margin: 10px; border-radius: 8px; }
.card-header { font-weight: bold; margin-bottom: 5px; background-color: #f0f0f0; padding: 5px; }
.card-body { border-top: 1px solid #eee; border-bottom: 1px solid #eee; padding: 10px 0; }
.card-footer { font-size: 0.8em; color: #666; margin-top: 5px; }
</style>

// App.vue (Parent Component)
<template>
  <CardComponent>
    <!-- Named Slot for header, accessing slot props -->
    <template #header="{ title }">
      <h2>{{ title }} - Custom Header!</h2>
    </template>

    <!-- Default Slot (implicitly 'default'), accessing slot props -->
    <template #default="{ contentData }">
      <p style="color: blue;">Overridden body: {{ contentData.toUpperCase() }}</p>
      <button @click="alert('Action!')">Click Me</button>
    </template>

    <!-- Named Slot for footer -->
    <template #footer>
      <small>Posted 2 days ago.</small>
    </template>
  </CardComponent>

  <CardComponent>
    <!-- No slots provided, default content will render -->
  </CardComponent>
</template>

<script setup>
import CardComponent from './CardComponent.vue';
</script>
How it works: This example showcases Vue 3's powerful scoped slots, which allow child components to provide data to their slot content, which is rendered by the parent component. `CardComponent` defines named slots (`header`, `footer`) and a default slot, passing data like `title` and `contentData` to them. The parent (`App.vue`) then uses `<template #slotName="{ propName }">` to receive this data and render custom content, enabling highly flexible and reusable UI components.

Need help integrating this into your project?

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

Hire DigitalCodeLabs