\n\n// РодительскийComponent.vue\n\n```\n\n## Как это работает внутри\n\n```javascript\n// Дочерний компонент определяет слот и передаёт данные\n\n\n// Эти данные становятся доступны в родительском компоненте\n\n\n// Vue распаковывает объект и делает item и index доступными в шаблоне\n```\n\n## Пример: Таблица с кастомным форматированием\n\n```javascript\n// DataTable.vue\n\n\n// В родительском компоненте\n\n```\n\n## Продвинутый пример: Modal с контролем содержимого\n\n```javascript\n// Modal.vue\n\n\n\n```\n\n## Отличие обычного слота от scoped slot\n\n```javascript\n// Обычный слот: родитель НЕ имеет доступ к данным дочернего\nDefault content\n\n// Scoped slot: родитель ИМЕЕТ доступ к данным дочернего\nDefault content\n\n// Использование\n\n \n\n```\n\n## Когда использовать scoped slots?\n\n```javascript\n// Используй для:\n// 1. Компонентов с логикой, но без контроля представления\n// 2. Повторяемых элементов (списки, таблицы)\n// 3. Модальных окон, drawer-ов, dropdown-ов\n// 4. Компонентов с условным рендерингом\n\n// Не используй если:\n// 1. Компонент полностью управляет представлением\n// 2. Нет необходимости передавать данные родителю\n// 3. Достаточно простого наследования props\n```","dateCreated":"2026-04-03T17:55:08.085521","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как работает scoped слот?

1.7 Middle🔥 252 комментариев
#JavaScript Core

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое scoped slot?

Scoped slot (областной слот) — это мощный паттерн в Vue.js, который позволяет родительскому компоненту получить доступ к данным из дочернего компонента при рендеринге шаблона. В отличие от обычных слотов, где дочерний компонент контролирует содержимое, scoped slots предоставляют данные от дочернего компонента, которые родитель может использовать для рендеринга.

Базовый пример scoped slot

// ДочерниеComponent.vue
<template>
  <div>
    <h3>{{ title }}</h3>
    <ul>
      <li v-for="item in items" :key="item.id">
        <slot name="item" :item="item" :index="index">
          {{ item.name }}
        </slot>
      </li>
    </ul>
  </div>
</template>

<script setup>
defineProps({
  title: String,
  items: Array
});
</script>

// РодительскийComponent.vue
<template>
  <ChildComponent :title=""Items"" :items="items">
    <template #item="{ item, index }">
      <strong>{{ index + 1 }}. {{ item.name }} - {{ item.price }}$</strong>
    </template>
  </ChildComponent>
</template>

Как это работает внутри

// Дочерний компонент определяет слот и передаёт данные
<slot name="item" :item="item" :index="index">

// Эти данные становятся доступны в родительском компоненте
<template #item="{ item, index }">
  {{ item.name }}
</template>

// Vue распаковывает объект и делает item и index доступными в шаблоне

Пример: Таблица с кастомным форматированием

// DataTable.vue
<template>
  <table>
    <thead>
      <tr>
        <th v-for="column in columns" :key="column.key">
          {{ column.label }}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(row, rowIndex) in data" :key="rowIndex">
        <td v-for="column in columns" :key="column.key">
          <slot
            :name="`cell-${column.key}`"
            :row="row"
            :column="column"
            :value="row[column.key]"
            :rowIndex="rowIndex"
          >
            {{ row[column.key] }}
          </slot>
        </td>
      </tr>
    </tbody>
  </table>
</template>

// В родительском компоненте
<template>
  <DataTable :columns="columns" :data="users">
    <template #cell-status="{ value }">
      <span :class="`badge badge-${value.toLowerCase()}`">
        {{ value }}
      </span>
    </template>
    
    <template #cell-actions="{ row }">
      <button @click="editUser(row)">Edit</button>
      <button @click="deleteUser(row)">Delete</button>
    </template>
  </DataTable>
</template>

Продвинутый пример: Modal с контролем содержимого

// Modal.vue
<template>
  <div v-if="isOpen" class="modal-overlay" @click="closeModal">
    <div class="modal-content" @click.stop>
      <div class="modal-header">
        <slot name="header" :title="title">
          <h2>{{ title }}</h2>
        </slot>
      </div>

      <div class="modal-body">
        <slot :data="data" :loading="loading">
          <p>No content provided</p>
        </slot>
      </div>

      <div class="modal-footer">
        <slot name="footer" :close="closeModal" :submit="submitModal">
          <button @click="closeModal">Cancel</button>
          <button @click="submitModal">OK</button>
        </slot>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";

const props = defineProps({
  title: String,
  data: Object
});

const emit = defineEmits(["update:open", "submit"]);

const isOpen = ref(true);
const loading = ref(false);

const closeModal = () => {
  isOpen.value = false;
  emit("update:open", false);
};

const submitModal = async () => {
  loading.value = true;
  loading.value = false;
  emit("submit");
  closeModal();
};
</script>

Отличие обычного слота от scoped slot

// Обычный слот: родитель НЕ имеет доступ к данным дочернего
<slot>Default content</slot>

// Scoped slot: родитель ИМЕЕТ доступ к данным дочернего
<slot :item="item" :index="index">Default content</slot>

// Использование
<MyComponent>
  <template #default="{ item, index }">
    {{ index }}: {{ item.name }}
  </template>
</MyComponent>

Когда использовать scoped slots?

// Используй для:
// 1. Компонентов с логикой, но без контроля представления
// 2. Повторяемых элементов (списки, таблицы)
// 3. Модальных окон, drawer-ов, dropdown-ов
// 4. Компонентов с условным рендерингом

// Не используй если:
// 1. Компонент полностью управляет представлением
// 2. Нет необходимости передавать данные родителю
// 3. Достаточно простого наследования props
Как работает scoped слот? | PrepBro