Именованные слоты
У панели одно место для содержимого. А для меню нужны карточки с тремя местами: заголовок сверху, цена посередине и кнопка внизу, каждое в своей части карточки, с линиями между ними. У компонента может быть несколько слотов, если дать им имена. Вот MenuCard.vue:
<template>
<article class="card">
<header>
<slot name="header" />
</header>
<div class="body">
<slot />
</div>
<footer>
<slot name="footer" />
</footer>
</article>
</template><slot> без имени — это слот по умолчанию. Родитель заполняет именованный слот элементом <template> с # и именем слота:
<MenuCard>
<template #header>
<h2>Морковный торт</h2>
</template>
<p>€4</p>
<template #footer>
<button>Добавить</button>
</template>
</MenuCard>Сами элементы <template> на странице не появляются, только их содержимое: заголовок попадает в header карточки, а кнопка — в её footer. Абзац не лежит ни в одном <template #…>, поэтому он попадает в слот по умолчанию. Порядок в родителе не важен: куда попадёт каждая часть, решает шаблон карточки.
#header — сокращение от v-slot:header, как @click — сокращение от v-on:click. В чужом коде вы увидите оба варианта; в этом курсе используется #. А слот по умолчанию называется default, поэтому его содержимое можно поместить и в <template #default>.
Зачем слот для заголовка, если у панели был проп title? Для короткого текста пропса хватает. Здесь же рядом с названием в заголовке есть ещё и метка с категорией, а в другой карточке на этом месте могла бы быть картинка. Правило такое: данные и короткие тексты передают в пропсах, куски страницы — в слотах. У компонента могут быть и те и другие, как у панели.
Типичные ошибки:
- Содержимое именованного слота лежит не в
<template #…>. Оно попадает в слот по умолчанию, поэтому показывается посреди карточки. - В карточке и в родителе разные имена, например
<slot name="footer" />и<template #foot>. Именованный слот, который ничем не заполнен, остаётся пустым, а содержимое для слота, которого в карточке нет, не показывается, и в обоих случаях без предупреждения. #на элементе, который не<template>, например<button #footer>. Это ошибка в файле, и красная полоса под превью укажет, где она, и напишетv-slot can only be used on components or <template> tags.
Задание
- 1
В
MenuCard.vueпоместите слот с именемheaderв элементheader. ВApp.vueпоместите заголовок каждой карточки в<template #header>. - 2
Сделайте то же для кнопки: слот с именем
footerв элементеfooterкарточки, а кнопка — в<template #footer>.