Named slots let you put different content in specific places inside a component. Scoped slots let the component share data with the content you put inside it.
Named slots and scoped slots in Vue
<template> <slot name="slotName">Default content</slot> </template> <!-- Using named slot --> <ChildComponent> <template #slotName> Custom content here </template> </ChildComponent> <!-- Scoped slot syntax --> <ChildComponent> <template #slotName="slotProps"> {{ slotProps.someData }} </template> </ChildComponent>
Named slots use the name attribute to identify different slots.
Scoped slots pass data from the child component to the parent using slot props.
<!-- ChildComponent.vue --> <template> <header><slot name="header">Default Header</slot></header> <main><slot>Default Body</slot></main> <footer><slot name="footer">Default Footer</slot></footer> </template>
<!-- Using ChildComponent with named slots -->
<ChildComponent>
<template #header>
<h1>My Custom Header</h1>
</template>
<p>This is the main body content.</p>
<template #footer>
<small>Custom footer text</small>
</template>
</ChildComponent>itemText to the slot as a prop named text.<!-- ChildComponent.vue with scoped slot --> <template> <slot name="item" :text="itemText"></slot> </template> <script setup> const itemText = 'Hello from child' </script>
text from the child and displays it inside the slot content.<!-- Using scoped slot -->
<ChildComponent>
<template #item="{ text }">
<p>Received: {{ text }}</p>
</template>
</ChildComponent>This example shows a card component with named slots for header and footer. The parent fills these slots with custom content and uses the default slot for the main body.
<!-- Card.vue --> <template> <div class="card"> <header class="card-header"> <slot name="header">Default Header</slot> </header> <section class="card-body"> <slot>Default Body Content</slot> </section> <footer class="card-footer"> <slot name="footer">Default Footer</slot> </footer> </div> </template> <style scoped> .card { border: 1px solid #ccc; padding: 1rem; border-radius: 0.5rem; max-width: 300px; } .card-header, .card-footer { background: #f0f0f0; padding: 0.5rem; } .card-body { padding: 1rem 0; } </style> <!-- App.vue --> <template> <Card> <template #header> <h2>Welcome!</h2> </template> <p>This is the main card content.</p> <template #footer> <button @click="alert('Clicked!')">Click me</button> </template> </Card> </template> <script setup> import Card from './Card.vue' </script>
Always provide default slot content to keep your component usable without custom slots.
Use v-bind or : to pass multiple props in scoped slots.
Named slots help organize complex components with multiple customizable parts.
Named slots let you put different content in specific places inside a component.
Scoped slots let the child component share data with the slot content.
Use named and scoped slots to build flexible, reusable Vue components.
Practice
Solution
Step 1: Understand named slots concept
Named slots allow you to define multiple placeholders inside a component where different content can be inserted.Step 2: Identify the purpose of named slots
They help organize content by placing it in specific parts of the component template.Final Answer:
To place different content in specific parts of a component -> Option DQuick Check:
Named slots = specific content placement [OK]
- Confusing named slots with props
- Thinking named slots share data
- Mixing named slots with lifecycle hooks
header inside a Vue component?Solution
Step 1: Recall named slot syntax in Vue
Named slots are defined using the element with a name attribute.Step 2: Match correct syntax
The correct syntax is . Other options are invalid or deprecated.Final Answer:
<slot name="header"></slot> -> Option CQuick Check:
Named slot syntax = <slot name="..."> [OK]
- Using which is deprecated
- Trying to create custom tags like
- Confusing named slots with props
<MyList>
<template #item="{ item }">
<li>{{ item.text }}</li>
</template>
</MyList>And this child component template:
<ul> <slot name="item" :item="listItem"></slot> </ul>
What will be rendered if
listItem is { text: 'Hello' }?Solution
Step 1: Understand scoped slot data passing
The child passeslistItemasitemto the slot content using:item="listItem".Step 2: Parent uses slot scope to access
The parent template receivesitem.textitemand renders<li>{{ item.text }}</li>, which becomes<li>Hello</li>.Final Answer:
<ul><li>Hello</li></ul> -> Option AQuick Check:
Scoped slot passes data = rendered content [OK]
- Ignoring the slot scope and expecting raw slot tags
- Not using the slot props correctly in parent
- Confusing named slots with scoped slots
<MyComponent> <template slot="footer">Footer Content</template> </MyComponent>
Assuming
MyComponent defines a named slot footer using <slot name="footer">.Solution
Step 1: Check slot syntax in Vue 3
Theslotattribute ontemplateis deprecated in Vue 3.Step 2: Identify correct syntax for named slots
Usev-slot:footeror shorthand#footerinstead ofslot="footer".Final Answer:
Using deprecatedslotattribute instead of#footershorthand -> Option BQuick Check:
Use v-slot or # for named slots [OK]
- Using old slot attribute syntax
- Confusing slot definition with slot usage
- Thinking no syntax change in Vue 3
Card component with named slots for header, body, and footer. The body slot should receive a scoped prop info from the component. Which is the correct way to define the Card template?Solution
Step 1: Identify named slots and scoped props
Thebodyslot must receive the scoped propinfofrom the component's data.Step 2: Check slot definitions
Only thebodyslot has:info='cardInfo'to pass the scoped prop. The others are simple named slots without props.Final Answer:
Correct template with named slots and scoped prop on body slot -> Option AQuick Check:
Scoped prop on body slot only [OK]
- Passing scoped props on wrong slots
- Missing scoped prop on body slot
- Using default slot instead of named slots
Ready to prove it?
Pass the test and this pattern moves unknown
