Слоты: default, named, scoped

↑ 4.1 Vue 3: основы, компоненты, Composition API · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

Слоты — основа гибких компонентов (таблицы, карточки, модалки); 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="..." /> допустим.

Практика

  1. Сделайте Modal со слотами header/default/footer.
  2. Реализуйте DataTable со scoped-слотом для ячеек.
  3. Добавьте типизацию defineSlots.

Вопросы с ответами

Связанные темы