Что такое слоты?vue-29

Основное понятие слотов

Слоты — это специальные места в компоненте, куда можно вставлять произвольное содержимое из родительского компонента. Они позволяют создавать гибкие и переиспользуемые компоненты-контейнеры.

Аналогия из реального мира

Представьте шаблон письма с "дырками", куда можно вставить разные тексты. Сам шаблон — это компонент, а "дырки" — слоты.

Основные типы слотов

1. Базовый слот

Компонент:

<template>
  <div class="card">
    <slot>Fallback content</slot>
  </div>
</template>

Использование:

<my-card>
  <h2>Мой заголовок</h2>
  <p>Произвольный контент</p>
</my-card>

2. Именованные слоты

Компонент:

<template>
  <div class="layout">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

Использование:

<app-layout>
  <template v-slot:header>
    <h1>Заголовок страницы</h1>
  </template>

  <p>Основное содержимое</p>

  <template #footer> <!-- сокращенный синтаксис -->
    <p>Контактная информация</p>
  </template>
</app-layout>

3. Scoped Slots

Позволяют дочернему компоненту передавать данные в слот.

Компонент:

<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      <slot :item="item" :index="index"></slot>
    </li>
  </ul>
</template>

<script>
export default {
  props: ['items']
}
</script>

Использование:

<item-list :items="products">
  <template v-slot:default="slotProps">
    {{ slotProps.index }}. {{ slotProps.item.name }} - {{ slotProps.item.price }}₽
  </template>
</item-list>

4. Динамические имена слотов

<template v-slot:[dynamicSlotName]>
  Динамический контент
</template>

Особенности работы слотов

  1. Слоты не являются реактивными — содержимое компилируется в родительском компоненте
  2. Можно использовать несколько раз — с помощью v-for или условного рендеринга
  3. Доступ к данным — в слоте доступны данные родительского компонента
  4. Стилизация — scoped-стили применяются к содержимому слотов

Практические примеры использования

1. Компонент модального окна

<!-- Modal.vue -->
<template>
  <div class="modal">
    <div class="modal-header">
      <slot name="header"></slot>
    </div>
    <div class="modal-body">
      <slot></slot>
    </div>
    <div class="modal-footer">
      <slot name="footer"></slot>
    </div>
  </div>
</template>

2. Компонент таблицы с гибким содержимым

<!-- DataTable.vue -->
<template>
  <table>
    <thead>
      <tr>
        <slot name="header"></slot>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(item, index) in data" :key="item.id">
        <slot :row="item" :index="index"></slot>
      </tr>
    </tbody>
  </table>
</template>

3. Компонент карточки с разными вариантами содержимого

<!-- ProductCard.vue -->
<template>
  <div class="card">
    <slot name="image">
      <img :src="defaultImage" class="card-img">
    </slot>
    <div class="card-body">
      <slot name="title">
        <h4>{{ product.name }}</h4>
      </slot>
      <slot></slot>
    </div>
  </div>
</template>

Нововведения Vue 3

  1. Единый синтаксис v-slot для всех случаев
  2. Упрощенный синтаксис для scoped slots:
<template #default="{ item, index }">
  {{ index }}. {{ item.name }}
</template>
  1. $slots в Composition API:
import { useSlots } from 'vue'

const slots = useSlots()
if (slots.header) {
  // есть контент для слота header
}

Резюмируем:

Слоты в Vue — это мощный механизм для создания компонентов-контейнеров с гибкой структурой, позволяющий инкапсулировать логику компонента, но оставлять свободу для кастомизации его содержимого. Они особенно полезны для создания UI-библиотек и сложных композиций компонентов.