AcademyVue
Slots: Passing Templates, Not Just Values
A slot is a function a parent hands its child — calling it renders the parent's markup, and calling it with data makes that markup scoped.
2 min readUpdated 3 exercises
A slot is content the parent writes, rendered where the child decides
Props pass data down; slots pass markup down. Anywhere a component writes <slot />, the parent's own template content appears:
<!-- Card.vue -->
<template>
<div class="card"><slot /></div>
</template>
<!-- usage -->
<Card><p>Whatever the parent puts here renders inside .card.</p></Card>Under the hood, slots.default in the child's setup is a function — calling it, slots.default(), is what actually produces the VNodes to render. Checking that the slot exists (slots.header ? ... : null) without calling it is a real, common mistake: existence and content are two different questions, and only calling the function answers the second one.
Named slots let a component take more than one piece of markup
<template>
<div class="card">
<header><slot name="header" /></header>
<div class="body"><slot /></div>
</div>
</template>
<!-- usage -->
<Card>
<template #header><h2>Title</h2></template>
<p>Body content — the unnamed, default slot.</p>
</Card>#header is shorthand for v-slot:header; the unnamed slot is always default, whether written explicitly as <template #default> or, as above, just placed directly inside the component tag.
Scoped slots hand data back up to the parent's template
A slot function can take an argument, and the parent destructures it in the #name="{ ... }" syntax — the mechanism behind every "renderless" or "headless" component pattern:
<!-- ItemList.vue -->
<template>
<ul>
<li v-for="item in items" :key="item.id">
<slot :item="item" />
</li>
</ul>
</template>
<!-- usage -->
<ItemList :items="items">
<template #default="{ item }">{{ item.name.toUpperCase() }}</template>
</ItemList>ItemList owns the looping and the <li> structure; the parent owns exactly how each item renders, without ItemList needing to know anything about that presentation. Calling the slot with no argument — slots.default() instead of slots.default({ item }) — is the scoped-slot equivalent of the named-slot bug above: the function runs, but the parent's { item } destructure receives undefined.
What interviewers check
Whether "what is a slot" gets an answer about functions, not just markup — the moment scoped slots come up, "a slot is a function the child calls, optionally with data" is the mental model that actually explains why passing props to it works at all.
Now practice it
2 quizzes · 1 drillReading this page is the cheap half. These are the exercises that make you use it.
- SlotsProA named slot checked but never called, and a scoped slot called with no props — both fixed in one exercise.DrillSolve · MediumDrillSolve · Medium
- Options API · Advanced PatternsAdvanced-tier Vue Fundamentals questions that assume slots, named and scoped, are already familiar.QuizTake · HardQuizTake · Hard
- Composition API · ref & reactiveSlots are read through the setup context's second argument — this set reinforces that same Composition API shape.QuizTake · EasyQuizTake · Easy
Read next
Props & Component Events
Props flow down, events flow up — and the object syntax for both is what actually gives you defaults, validation and v-model.
2 min
Provide / Inject: Skipping the Prop Chain
provide() and inject() pass data straight to any descendant, no matter how deep — but only stay reactive when what you provide is itself reactive.
2 min