codejump

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

Waiting at the end of this page.

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:

vue
<!-- 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

vue
<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:

vue
<!-- 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 drill

Reading this page is the cheap half. These are the exercises that make you use it.