Слоты: default, named, scoped
↑ 4.1 Vue 3: основы, компоненты, Composition API · ← Предыдущая · → Следующая
Зачем это на собесе
Слоты — основа гибких компонентов (таблицы, карточки, модалки); scoped-слоты — «render props» Vue.
Объяснение
Слот позволяет родителю передать разметку внутрь дочернего компонента.
<!-- Card.vue -->
<template>
<article class="card">
<header><slot name="header">Заголовок по умолчанию</slot></header>
<div class="body"><slot /></div> <!-- default -->
<footer><slot name="footer" :close="close" :count="items.length" /></footer> <!-- scoped: данные вниз -->
</article>
</template>
<!-- Использование -->
<Card>
<template #header><h3>Заказы</h3></template>
<p>Основное содержимое</p>
<template #footer="{ close, count }"><button @click="close">Закрыть ({{ count }})</button></template>
</Card>| Вид | Смысл |
|---|---|
| Default | безымянный <slot /> |
| Named | <slot name="x"> + #x (v-slot:x) |
| Scoped | слот передаёт данные родителю: <slot :item="item"> + #default="{ item }" |
| Fallback | содержимое по умолчанию внутри <slot> |
| Динамические имена | <template #[dynamicName]> |
| Проверка | $slots.header, useSlots() — есть ли слот |
Пример scoped-слота в таблице:
<DataTable :rows="orders" :columns="columns">
<template #cell-status="{ row }"><StatusBadge :value="row.status" /></template>
<template #empty>Нет данных</template>
</DataTable>Типизация слотов: defineSlots<{ default(props: {}): any; item(props: { row: Order }): any }>().
Области видимости: содержимое слота компилируется в контексте родителя (видит его состояние), но получает данные потомка только через scoped-props.
Нюансы и подводные камни
- Нельзя обратиться к состоянию потомка из слота без scoped-props.
- Условный рендеринг обёрток: проверьте
$slots.headerперед выводом контейнера. - Слоты могут вызывать лишние перерендеры потомка; стабильные ссылки на данные.
- Слоты в
<script setup>:useSlots(). - Слот и
v-for:<slot v-for="..." />допустим.
Практика
- Сделайте
Modalсо слотами header/default/footer. - Реализуйте
DataTableсо scoped-слотом для ячеек. - Добавьте типизацию
defineSlots.
Вопросы с ответами
Что такое scoped slot?
Слот, передающий данные из компонента-потомка в контент родителя через props слота.
Кому принадлежит область видимости содержимого слота?
Родителю: слот видит его переменные, но не состояние потомка без scoped-props.