Слоты во Vue.js используются для композиции компонентов и передачи разметки извне внутрь компонента. Именованные и scoped слоты расширяют базовый механизм, позволяя строить гибкие, переиспользуемые интерфейсные компоненты без жёсткой привязки к структуре DOM.
По умолчанию компонент имеет один слот без имени. Для размещения нескольких независимых областей вставки применяются именованные слоты.
<!-- BaseLayout.vue -->
<template>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</template>
Здесь:
header и footer — именованные.<BaseLayout>
<template v-slot:header>
<h1>Заголовок страницы</h1>
</template>
<p>Основное содержимое</p>
<template v-slot:footer>
<small>Подвал</small>
</template>
</BaseLayout>
Ключевые особенности:
v-slot используется только на
<template> или компоненте;<template v-slot:...>
автоматически попадает в дефолтный слот.<template #header>
<h1>Заголовок</h1>
</template>
# является сокращением для v-slot: и
применяется повсеместно в актуальном коде Vue 3.
Если слот не был передан, компонент может отобразить запасное содержимое.
<slot name="footer">
<span>Значение по умолчанию</span>
</slot>
Fallback-контент отображается только при отсутствии соответствующего слота у компонента-потребителя.
Scoped слоты позволяют компоненту передавать данные во внешний шаблон слота. Это основной механизм разделения логики и представления.
<!-- UserList.vue -->
<template>
<ul>
<li v-for="user in users" :key="user.id">
<slot :user="user" :is-active="user.active"></slot>
</li>
</ul>
</template>
<script>
export default {
props: {
users: Array
}
}
</script>
Атрибуты слота (:user, :is-active)
формируют объект параметров слота.
<UserList :users="users">
<template #default="{ user, isActive }">
<span :class="{ active: isActive }">
{{ user.name }}
</span>
</template>
</UserList>
Принцип работы:
Именованные слоты также могут быть scoped.
<slot name="item" :value="item" :index="index"></slot>
<template #item="{ value, index }">
<div>{{ index }} — {{ value }}</div>
</template>
Такой подход часто применяется в списках, таблицах, дропдаунах, календарях.
Scoped-слоты поддерживают стандартную деструктуризацию JavaScript.
<template #default="{ user: u }">
{{ u.name }}
</template>
Допустимо задание значений по умолчанию:
<template #default="{ isActive = false }">
{{ isActive }}
</template>
Vue поддерживает вычисляемые имена слотов.
<template v-slot:[slotName]>
Динамический слот
</template>
slotName — строковое значение, определённое в контексте
компонента.
Применение:
Компонент может передавать полученные слоты дальше, не зная их структуры.
<template>
<ChildComponent>
<slot name="header"></slot>
<slot></slot>
</ChildComponent>
</template>
Для scoped-слотов используется проброс параметров:
<slot name="item" v-bind="slotProps"></slot>
<template>
<slot name="title" :count="items.length"></slot>
<slot name="item" v-for="item in items" :item="item"></slot>
</template>
Использование:
<MyComponent>
<template #title="{ count }">
Всего: {{ count }}
</template>
<template #item="{ item }">
{{ item.name }}
</template>
</MyComponent>
Props:
Scoped-слоты:
Scoped-слоты используются, когда компонент:
v-slot вне компонента;Vue 3 унифицировал API:
slot-scope удалён;v-slot;# — стандартный шорткат;Это делает код компактнее и предсказуемее при масштабировании.
Именованные и scoped слоты формируют основу архитектуры компонентных библиотек во Vue.js, позволяя строить абстрактные компоненты с чётким разделением ответственности между логикой и представлением.