Scoped slots — это механизм, который позволяет передавать данные из дочернего компонента в слот родителя, создавая динамические и настраиваемые интерфейсы. В отличие от обычных слотов, которые просто отображают переданный контент, scoped slots предоставляют контекстные данные, доступные внутри слота, что делает их незаменимыми при работе с повторяющимися компонентами, таблицами, списками и динамическими элементами UI.
В Vuetify каждый компонент с поддержкой scoped slots предоставляет
объект с данными, доступными в слоте через директиву
v-slot. Синтаксис выглядит следующим образом:
<v-data-table :items="users">
<template v-slot:item="{ item }">
<tr>
<td>{{ item.name }}</td>
<td>{{ item.email }}</td>
<td>{{ item.role }}</td>
</tr>
</template>
</v-data-table>
Разбор примера:
v-data-table — компонент Vuetify для отображения
таблиц.v-slot:item — слот для рендеринга каждой строки
таблицы.{ item } — деструктуризация объекта, который
предоставляет компонент (каждая строка данных). Через item
можно получить свойства каждой записи.Scoped slots передают объект со множеством полей,
зависящих от компонента. Например, у v-data-table
доступны:
item — объект данных текущей строки.index — индекс элемента в массиве.selected — булево значение, показывающее, выделена ли
строка.isExpanded — состояние раскрытой строки (если
используется expandable row).Использование нескольких полей:
<v-data-table :items="users">
<template v-slot:item="{ item, index, selected }">
<tr :class="{ 'highlighted': selected }">
<td>{{ index + 1 }}</td>
<td>{{ item.name }}</td>
<td>{{ item.email }}</td>
</tr>
</template>
</v-data-table>
Scoped slots позволяют создавать полностью кастомные элементы, используя данные родительского компонента. Например, список карточек с динамическим контентом:
<v-card v-for="product in products" :key="product.id">
<template v-slot:default="{ product }">
<v-card-title>{{ product.title }}</v-card-title>
<v-card-text>{{ product.description }}</v-card-text>
</template>
</v-card>
Если компонент сам предоставляет контекстные данные для слота, они могут использоваться для отображения состояния, событий и вычислений прямо в родителе.
Vuetify поддерживает передачу функций через слоты, что позволяет управлять поведением компонента внутри слота. Пример с кнопкой действия в строке таблицы:
<v-data-table :items="tasks">
<template v-slot:item.action="{ item }">
<v-btn color="primary" @click="completeTask(item.id)">
Завершить
</v-btn>
</template>
</v-data-table>
Здесь:
completeTask — метод родительского компонента.item предоставляет доступ к уникальному идентификатору
задачи.Scoped slots особенно полезны для компонентов с повторяющимися
элементами, таких как v-list и v-data-table.
Например, можно полностью контролировать отображение элементов
списка:
<v-list :items="messages">
<template v-slot:default="{ item, index }">
<v-list-item :key="index">
<v-list-item-content>
<v-list-item-title>{{ item.sender }}</v-list-item-title>
<v-list-item-subtitle>{{ item.text }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</template>
</v-list>
Преимущества такого подхода:
Scoped slots удобно сочетать с кастомными событиями. Например, таблица с возможностью редактирования строк:
<v-data-table :items="products">
<template v-slot:item.edit="{ item }">
<v-btn icon @click="$emit('edit-product', item)">
<v-icon>mdi-pencil</v-icon>
</v-btn>
</template>
</v-data-table>
Преимущества:
item.edit-product) с полным контекстом.Vuetify позволяет одновременно использовать несколько слотов с
разными контекстами. Пример для v-data-table:
<v-data-table :items="users">
<template v-slot:item.name="{ item }">
<strong>{{ item.name }}</strong>
</template>
<template v-slot:item.email="{ item }">
<a :href="`mailto:${item.email}`">{{ item.email }}</a>
</template>
<template v-slot:item.role="{ item }">
<v-chip>{{ item.role }}</v-chip>
</template>
</v-data-table>
Каждый слот получает одинаковый контекст (item), но
позволяет разделить логику и стили для разных
колонок.
v-slot:expanded-item с item для создания
раскрывающихся деталей.v-slot:header для
управления заголовками таблицы.v-slot:item.action
для кнопок управления каждой записью.v-if внутри слота для изменения контента в зависимости от
состояния.Scoped slots в Vuetify — это мощный инструмент, который превращает компоненты в гибкие и переиспользуемые элементы интерфейса, позволяя полностью контролировать их разметку, стили и поведение без изменения исходного компонента.