A Component with a Slot
The café's page has several boxes that look the same: a white box with a border and a heading, and in it, something different each time. The opening hours are a paragraph, the menu is a list, and the order is a list with a button. One component for the box would be handy, but props don't fit here. A prop carries a value, such as a text or an object, and this box has to carry a piece of the page.
For that, a component has a slot: a place in its template that its parent fills. Here's Panel.vue, a box with a heading from its prop title and a slot under the heading:
<script setup>
defineProps({
title: { type: String, required: true },
});
</script>
<template>
<section class="panel">
<h2>{{ title }}</h2>
<slot />
</section>
</template>The parent writes the component with an opening and a closing tag, and puts the content between them, as it would with an HTML element:
<Panel title="Opening hours">
<p>Every day from 7 am to 7 pm.</p>
</Panel>Vue shows the panel's template, with the content in place of <slot />. The page gets:
<section class="panel">
<h2>Opening hours</h2>
<p>Every day from 7 am to 7 pm.</p>
</section>The content can be anything you'd write in a template: text, several elements, a list with v-for, even other components. And each time you use the panel, you can give it different content.
Until now, your components had nothing between their tags, so you wrote them self-closing, as <MenuItem />. And a component without <slot /> does nothing with the content between its tags: Vue leaves it out, without a warning. When content doesn't show up, check first that the component has a slot.
Instructions
- 1
In
Panel.vue, put<slot />under the heading, so that the panel with the opening hours shows its paragraph. - 2
In
App.vue, add a second panel under the first one, with the titleToday's cakeand the paragraphCarrot Cake with walnuts, €4.