\n\n// Использование\n\n\n\n```\n\n### Решение 2: Использовать $slots с рендер-функцией\n\nОбратитесь к слотам через `$slots` и рендерьте их динамически:\n\n```javascript\n// DynamicSlotComponent.vue\n\n\n\n\n// Использование\n\n```\n\n### Решение 3: Массив объектов с контентом (рекомендуется)\n\nСамый гибкий подход — передать массив данных и рендерить его:\n\n```javascript\n// GridLayout.vue\n\n\n\n\n// Использование\n\n\n\n```\n\n### Решение 4: Использовать render-функцию (Advanced)\n\nДля максимальной гибкости можно использовать render-функцию:\n\n```javascript\n// DynamicRenderer.vue\n\n\n// Использование\n\n```\n\n### Практический пример: Card Gallery\n\n```javascript\n// CardGallery.vue\n\n\n\n\n// Использование\n\n\n\n```\n\n### Лучшие практики\n\n1. **Используй prop-based approach** для количественно больших наборов данных\n2. **Используй именованные слоты** когда нужна гибкость в укрытии контента\n3. **Предусмотри контент по умолчанию** в слотах\n4. **Использовать scoped slots** для передачи данных в контент слота\n5. **Избегай большого кол-ва явных слотов** в шаблоне\n\n### Вывод\n\nДля создания компонента с неограниченным количеством слотов лучше всего использовать **prop-based approach** с массивом данных и **scoped slots** для кастомизации. Это обеспечивает гибкость, производительность и чистоту кода. Render-функции подходят для более сложных случаев, но усложняют отладку.","dateCreated":"2026-04-02T22:24:55.941226","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как создать компонент с неограниченным кол-вом слотов?

1.0 Junior🔥 72 комментариев
#React

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

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

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

Как создать компонент с неограниченным количеством слотов

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

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

Виды слотов

1. Обычный слот

// CardComponent.vue
<template>
  <div class="card">
    <slot></slot>
  </div>
</template>

// Родитель
<template>
  <Card>
    <p>Этот контент попадёт в слот</p>
  </Card>
</template>

2. Именованные слоты (Named Slots)

// CardComponent.vue
<template>
  <div class="card">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

// Родитель
<template>
  <Card>
    <template #header>
      <h1>Заголовок</h1>
    </template>
    <p>Содержимое по умолчанию</p>
    <template #footer>
      <button>Закрыть</button>
    </template>
  </Card>
</template>

Проблема: неограниченное кол-во слотов

Если вам нужно компонент с динамическим количеством слотов (например, до 100), есть несколько подходов.

Решение 1: Использовать default slot с component prop

После компонент, который принимает компоненты как параметры:

// FlexibleLayout.vue
<template>
  <div class="layout">
    <component 
      v-for="item in sections"
      :key="item.id"
      :is="item.component"
      :props="item.props"
    />
  </div>
</template>

<script>
export default {
  props: {
    sections: {
      type: Array,
      required: true
    }
  }
};
</script>

// Использование
<template>
  <FlexibleLayout :sections="sections" />
</template>

<script>
export default {
  data() {
    return {
      sections: [
        { id: 1, component: Header },
        { id: 2, component: Content },
        { id: 3, component: Sidebar },
        { id: 4, component: Footer }
      ]
    };
  }
};
</script>

Решение 2: Использовать $slots с рендер-функцией

Обратитесь к слотам через $slots и рендерьте их динамически:

// DynamicSlotComponent.vue
<template>
  <div class="container">
    <template v-for="(slotContent, slotName) in $slots" :key="slotName">
      <div class="slot-wrapper">
        <slot :name="slotName"></slot>
      </div>
    </template>
  </div>
</template>

<script>
export default {
  // Автоматически поддерживает все слоты
};
</script>

// Использование
<template>
  <DynamicSlotComponent>
    <template #section1>
      <h2>Раздел 1</h2>
    </template>
    <template #section2>
      <h2>Раздел 2</h2>
    </template>
    <template #section3>
      <h2>Раздел 3</h2>
    </template>
    <!-- Можно добавлять слоты динамически -->
  </DynamicSlotComponent>
</template>

Решение 3: Массив объектов с контентом (рекомендуется)

Самый гибкий подход — передать массив данных и рендерить его:

// GridLayout.vue
<template>
  <div class="grid">
    <div 
      v-for="item in items"
      :key="item.id"
      class="grid-item"
    >
      <slot 
        :name="`item-${item.id}`"
        :item="item"
      >
        <!-- Контент по умолчанию -->
        <p>{{ item.title }}</p>
      </slot>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    items: {
      type: Array,
      required: true
    }
  }
};
</script>

// Использование
<template>
  <GridLayout :items="items">
    <template #item-1="{ item }">
      <Card>{{ item.title }}</Card>
    </template>
    <template #item-2="{ item }">
      <Article>{{ item.content }}</Article>
    </template>
    <!-- По умолчанию для остальных items используется контент из слота -->
  </GridLayout>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, title: "Первый" },
        { id: 2, title: "Второй" },
        { id: 3, title: "Третий" },
        // ... сотни элементов
      ]
    };
  }
};
</script>

Решение 4: Использовать render-функцию (Advanced)

Для максимальной гибкости можно использовать render-функцию:

// DynamicRenderer.vue
<script>
export default {
  props: {
    sections: Array
  },
  render() {
    return (
      <div class="renderer">
        {this.sections.map((section, index) => (
          <div key={section.id} class="section">
            {this.$slots[`section-${section.id}`]?.() || 
             <p>{section.defaultContent}</p>
            }
          </div>
        ))}
      </div>
    );
  }
};
</script>

// Использование
<template>
  <DynamicRenderer :sections="sections">
    <template #section-1>
      <Header />
    </template>
    <template #section-2>
      <Main />
    </template>
  </DynamicRenderer>
</template>

Практический пример: Card Gallery

// CardGallery.vue
<template>
  <div class="gallery">
    <div 
      v-for="card in cards"
      :key="card.id"
      class="card"
    >
      <!-- Слот для каждой карточки -->
      <slot 
        :name="`card-${card.id}`"
        :card="card"
      >
        <!-- Контент по умолчанию -->
        <div class="card-default">
          <h3>{{ card.title }}</h3>
          <p>{{ card.description }}</p>
        </div>
      </slot>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    cards: {
      type: Array,
      default: () => []
    }
  }
};
</script>

// Использование
<template>
  <CardGallery :cards="products">
    <template #card-1="{ card }">
      <ProductCard :product="card" />
    </template>
    <template #card-2="{ card }">
      <PremiumCard :product="card" />
    </template>
    <!-- Остальные карточки используют контент по умолчанию -->
  </CardGallery>
</template>

<script>
export default {
  data() {
    return {
      products: [
        { id: 1, title: "Товар 1" },
        { id: 2, title: "Товар 2" },
        { id: 3, title: "Товар 3" },
        // ... может быть тысячи товаров
      ]
    };
  }
};
</script>

Лучшие практики

  1. Используй prop-based approach для количественно больших наборов данных
  2. Используй именованные слоты когда нужна гибкость в укрытии контента
  3. Предусмотри контент по умолчанию в слотах
  4. Использовать scoped slots для передачи данных в контент слота
  5. Избегай большого кол-ва явных слотов в шаблоне

Вывод

Для создания компонента с неограниченным количеством слотов лучше всего использовать prop-based approach с массивом данных и scoped slots для кастомизации. Это обеспечивает гибкость, производительность и чистоту кода. Render-функции подходят для более сложных случаев, но усложняют отладку.

Как создать компонент с неограниченным кол-вом слотов? | PrepBro