\n\n// App.vue — использование с доступом к user\n\n```\n\n## Слоты в веб-компонентах\n\n```html\n\n\n\n\n\n\n\n Important\n

This is important information

\n
\n```\n\n## Практические примеры\n\n### Компонент Dialog\n\n```javascript\n// Dialog.vue\n\n\n\n\n// Использование\n\n \n \n

Are you sure?

\n \n \n
\n```\n\n### Таблица с кастомизацией ячеек\n\n```javascript\n// DataTable.vue\n\n\n\n\n// Использование\n\n \n\n```\n\n## Преимущества слотов\n\n- **Переиспользуемость**: один компонент для разных сценариев\n- **Гибкость**: родитель контролирует содержимое\n- **Разделение ответственности**: компонент отвечает за стиль, родитель — за содержание\n- **Типизация**: с TypeScript можно типизировать слоты\n- **Реактивность**: слоты реактивны и обновляются при изменении данных\n\n## Итоги\n\n- Слоты — механизм для передачи содержимого в компоненты\n- Существуют именованные слоты и безымянные слоты\n- Scoped slots позволяют передавать данные в обратном направлении\n- Слоты есть в Vue.js, веб-компонентах и других фреймворках\n- Основной инструмент для создания гибких переиспользуемых компонентов","dateCreated":"2026-03-26T18:25:39.295096","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Что такое слоты?

2.0 Middle🔥 241 комментариев
#Vue.js

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

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

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

Что такое слоты

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

Концепция слотов

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

Слоты в Vue.js

Основной слот (Named Slot)

// Card.vue — компонент с слотом
<template>
  <div class="card">
    <div class="card-header">
      <slot name="header">Default Header</slot>
    </div>
    <div class="card-body">
      <slot>Default Content</slot>
    </div>
    <div class="card-footer">
      <slot name="footer">Default Footer</slot>
    </div>
  </div>
</template>

<style>
.card {
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 16px;
}
</style>

Использование слотов в родительском компоненте

// App.vue
<template>
  <Card>
    <template #header>
      <h2>My Custom Header</h2>
    </template>
    
    <template #default>
      <p>This is custom content for the card</p>
    </template>
    
    <template #footer>
      <button>Click me</button>
    </template>
  </Card>
</template>

Сокращенный синтаксис: #header вместо v-slot:header

Безымянный слот (Default Slot)

Если у компонента только один слот, можно использовать безымянный:

// Button.vue
<template>
  <button class="btn">
    <slot>Click me</slot>
  </button>
</template>

// Использование
<Button>Save Changes</Button>

Слоты с областью видимости (Scoped Slots)

Позволяют передавать данные из дочернего компонента в родительский:

// UserList.vue — компонент с данными
<template>
  <div class="user-list">
    <div v-for="user in users" :key="user.id" class="user-item">
      <slot name="user" :user="user">
        {{ user.name }}
      </slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      users: [
        { id: 1, name: 'Alice', status: 'active' },
        { id: 2, name: 'Bob', status: 'inactive' }
      ]
    }
  }
}
</script>

// App.vue — использование с доступом к user
<template>
  <UserList>
    <template #user="{ user }">
      <div class="custom-user">
        <strong>{{ user.name }}</strong>
        <span :class="user.status">{{ user.status }}</span>
      </div>
    </template>
  </UserList>
</template>

Слоты в веб-компонентах

<!-- modal.js -->
<template id="modal-template">
  <style>
    .modal {
      border: 1px solid #333;
      padding: 20px;
      border-radius: 8px;
    }
    .modal-header {
      font-weight: bold;
      margin-bottom: 10px;
    }
    .modal-body {
      margin: 10px 0;
    }
  </style>
  <div class="modal">
    <div class="modal-header">
      <slot name="header">Default Header</slot>
    </div>
    <div class="modal-body">
      <slot>Default Content</slot>
    </div>
  </div>
</template>

<script>
class Modal extends HTMLElement {
  connectedCallback() {
    const template = document.getElementById('modal-template');
    const clone = template.content.cloneNode(true);
    this.attachShadow({ mode: 'open' }).appendChild(clone);
  }
}

customElements.define('custom-modal', Modal);
</script>

<!-- Использование -->
<custom-modal>
  <span slot="header">Important</span>
  <p>This is important information</p>
</custom-modal>

Практические примеры

Компонент Dialog

// Dialog.vue
<template>
  <div v-if="isOpen" class="dialog-overlay">
    <div class="dialog">
      <div class="dialog-header">
        <slot name="header"></slot>
        <button @click="close">×</button>
      </div>
      <div class="dialog-body">
        <slot></slot>
      </div>
      <div class="dialog-footer">
        <slot name="footer">
          <button @click="close">Close</button>
        </slot>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: ['isOpen'],
  emits: ['close'],
  methods: {
    close() {
      this.$emit('close');
    }
  }
}
</script>

// Использование
<Dialog :isOpen="showDialog" @close="showDialog = false">
  <template #header>
    <h3>Confirm Action</h3>
  </template>
  
  <p>Are you sure?</p>
  
  <template #footer>
    <button @click="confirm">Yes</button>
    <button @click="close">No</button>
  </template>
</Dialog>

Таблица с кастомизацией ячеек

// DataTable.vue
<template>
  <table>
    <thead>
      <tr>
        <th v-for="col in columns" :key="col">
          {{ col }}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="row in rows" :key="row.id">
        <td v-for="col in columns" :key="col">
          <slot :name="col" :value="row[col]">
            {{ row[col] }}
          </slot>
        </td>
      </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  props: ['columns', 'rows']
}
</script>

// Использование
<DataTable :columns="['name', 'email', 'status']" :rows="users">
  <template #status="{ value }">
    <span :class="`badge-${value}`">{{ value }}</span>
  </template>
</DataTable>

Преимущества слотов

  • Переиспользуемость: один компонент для разных сценариев
  • Гибкость: родитель контролирует содержимое
  • Разделение ответственности: компонент отвечает за стиль, родитель — за содержание
  • Типизация: с TypeScript можно типизировать слоты
  • Реактивность: слоты реактивны и обновляются при изменении данных

Итоги

  • Слоты — механизм для передачи содержимого в компоненты
  • Существуют именованные слоты и безымянные слоты
  • Scoped slots позволяют передавать данные в обратном направлении
  • Слоты есть в Vue.js, веб-компонентах и других фреймворках
  • Основной инструмент для создания гибких переиспользуемых компонентов