Explain Slots in Vue: default vs named vs scoped slots — and how slot props enable child-to-parent data flow

HighIntermediateVue
Preparing for interviews?

Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.

Quick Answer

Explain how Vue slots work (default, named, and scoped slots), what problem they solve, and how slot props allow a child component to pass data back to the parent’s template while still keeping one-way data flow.

Answer

Core idea

Slots are Vue’s way of letting a parent inject template content into a child — while the child controls where and how that content is rendered. With scoped slots (slot props), the child can also expose data to the parent’s slot template, enabling a powerful, explicit, and safe form of child → parent data flow.

Slot type

What it does

When you use it

Default slot

Injects unnamed content into a child component

Simple wrapper components (Card, Modal, Layout, etc.)

Named slot

Lets you target multiple insertion points

Complex layouts (header/body/footer, actions, sidebars)

Scoped slot (slot props)

Child exposes data to the parent’s slot template

Reusable logic components (List, Table, Fetcher, Virtualizer)

The three kinds of slots in Vue

Default slot

The simplest case: the parent passes some markup, and the child decides where to render it.

HTML
<!-- Card.vue -->
<template>
  <div class="card">
    <slot />
  </div>
</template>

<!-- Parent.vue -->
<Card>
  <h2>Hello</h2>
  <p>This goes into the default slot</p>
</Card>
                  

Named slots

When a component has multiple insertion points, you name them.

HTML
<!-- Modal.vue -->
<template>
  <div class="modal">
    <header><slot name="header" /></header>
    <main><slot /></main>
    <footer><slot name="footer" /></footer>
  </div>
</template>

<!-- Parent.vue -->
<Modal>
  <template #header>
    <h2>Confirm</h2>
  </template>

  Are you sure?

  <template #footer>
    <button>OK</button>
  </template>
</Modal>
                  

The real power: scoped slots (slot props)

Normally, slot content is compiled in the parent’s scope. But sometimes the child has the data (e.g., a list, fetched results, virtualized rows). Scoped slots let the child expose data to the parent’s slot template explicitly.

HTML
<!-- ListRenderer.vue -->
<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      <slot :item="item" :index="item.id" />
    </li>
  </ul>
</template>

<script setup>
const props = defineProps({
  items: { type: Array, required: true }
});
</script>
                  

Now the parent can decide how each item is rendered, using data provided by the child:

HTML
<!-- Parent.vue -->
<ListRenderer :items="users">
  <template #default="{ item }">
    <strong>{{ item.name }}</strong> ({{ item.email }})
  </template>
</ListRenderer>
                  

Why this is not “breaking” one-way data flow

The child is not mutating parent state. It is only exposing data. The parent still decides what to render and what to do with that data. This is inversion of control, not two-way binding.

Without scoped slots

With scoped slots

Child controls both logic and rendering

Child controls logic, parent controls rendering

Low flexibility

Highly reusable and customizable components

Hard to generalize components

Enables headless / renderless components

Why scoped slots are a big deal

Common real-world use cases

- Table components (you provide column templates)

  • List / virtual scroller components
  • Data fetcher components
  • Form builders
  • Headless UI components

Interview-ready takeaway

Default slots inject content, named slots target multiple regions, and scoped slots let the child pass data into the parent’s slot template. This enables highly reusable components where the child owns the logic, the parent owns the rendering — without breaking one-way data flow.

Similar questions
Guides
1 / 34