Слоты — это специальные места в компоненте, куда можно вставлять произвольное содержимое из родительского компонента. Они позволяют создавать гибкие и переиспользуемые компоненты-контейнеры.
Представьте шаблон письма с "дырками", куда можно вставить разные тексты. Сам шаблон — это компонент, а "дырки" — слоты.
Компонент:
<template>
<div class="card">
<slot>Fallback content</slot>
</div>
</template>
Использование:
<my-card>
<h2>Мой заголовок</h2>
<p>Произвольный контент</p>
</my-card>
Компонент:
<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>
Позволяют дочернему компоненту передавать данные в слот.
Компонент:
<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>
<template v-slot:[dynamicSlotName]>
Динамический контент
</template>
v-for
или условного рендеринга<!-- 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>
<!-- 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>
<!-- 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>
<template #default="{ item, index }">
{{ index }}. {{ item.name }}
</template>
import { useSlots } from 'vue'
const slots = useSlots()
if (slots.header) {
// есть контент для слота header
}
Слоты в Vue — это мощный механизм для создания компонентов-контейнеров с гибкой структурой, позволяющий инкапсулировать логику компонента, но оставлять свободу для кастомизации его содержимого. Они особенно полезны для создания UI-библиотек и сложных композиций компонентов.