Stencil поддерживает концепцию слотов (slots) — механизм для вставки контента в компонент. Это мощный инструмент, который помогает строить гибкие и переиспользуемые компоненты. Однако иногда бывает необходимо работать не с одним, а с несколькими слотами. В этом случае Stencil предоставляет возможность использования множественных слотов для обеспечения более сложной и многофункциональной логики в компонентах.
Множественные слоты в Stencil позволяют компоненту принимать несколько фрагментов контента и распределять их в разные части шаблона. Каждый слот можно назначить уникальное имя, что позволяет управлять тем, какой контент куда попадет.
В HTML используется стандартный элемент <slot>, а
в Stencil можно добавить атрибут name, чтобы различать
слоты. Когда контент передается в компонент, каждый слот будет
соответствовать своему назначению.
Пример простого компонента с двумя слотами:
@Component({
tag: 'app-multi-slot',
styleUrl: 'app-multi-slot.css',
shadow: true
})
export class AppMultiSlot {
render() {
return (
<div>
<header>
<slot name="header-content"></slot>
</header>
<main>
<slot name="main-content"></slot>
</main>
</div>
);
}
}
В данном примере компонент app-multi-slot содержит два
слота — один для содержимого заголовка и второй для основного контента.
Они имеют уникальные имена, которые позволяют различать контент,
передаваемый в каждый слот.
Имена слотов важны, так как они позволяют точно указать, какой контент должен попасть в какой слот. Когда компонент с несколькими слотами используется в другом компоненте или в приложении, контент можно передавать по именам, как показано в следующем примере:
<app-multi-slot>
<div slot="header-content">
<h1>Заголовок страницы</h1>
</div>
<div slot="main-content">
<p>Основное содержание страницы.</p>
</div>
</app-multi-slot>
Здесь, используя атрибут slot, каждый блок контента
попадает в нужный слот компонента app-multi-slot. Важно,
что если имя слота не будет совпадать с именем, переданным в компоненте,
то этот контент не будет отображен.
Stencil также поддерживает слот по умолчанию, который используется,
если контент не был передан в слот с конкретным именем. Для этого
необходимо просто использовать слот без атрибута name.
Например:
@Component({
tag: 'app-default-slot',
styleUrl: 'app-default-slot.css',
shadow: true
})
export class AppDefaultSlot {
render() {
return (
<div>
<slot></slot> <!-- Слот по умолчанию -->
</div>
);
}
}
В этом примере любой контент, который будет передан в компонент, попадет в этот слот. Если же контент не передан, слот останется пустым.
Для реализации слота по умолчанию в случае с множественными слотами можно комбинировать именованные и неименованные слоты, чтобы обеспечить гибкость в размещении контента:
@Component({
tag: 'app-multi-slot-with-default',
styleUrl: 'app-multi-slot-with-default.css',
shadow: true
})
export class AppMultiSlotWithDefault {
render() {
return (
<div>
<header>
<slot name="header-content"></slot>
</header>
<main>
<slot name="main-content"></slot>
<slot></slot> <!-- Слот по умолчанию -->
</main>
</div>
);
}
}
В этом случае, если контент для именованных слотов не передан, слоты по умолчанию будут использоваться.
Одним из ключевых преимуществ множественных слотов является возможность детально распределять контент внутри компонента. Это особенно полезно в сложных интерфейсах, где необходимо отображать различные части контента в разных местах. Например, можно создать карточку с несколькими секциями:
@Component({
tag: 'app-card',
styleUrl: 'app-card.css',
shadow: true
})
export class AppCard {
render() {
return (
<div class="card">
<header>
<slot name="title"></slot>
</header>
<section>
<slot name="content"></slot>
</section>
<footer>
<slot name="footer"></slot>
</footer>
</div>
);
}
}
В этом примере компонент app-card содержит три различных
слота: для заголовка, основного контента и подвала. Каждое из этих мест
может быть заполнено контентом, переданным в компонент:
<app-card>
<div slot="title">Заголовок карточки</div>
<div slot="content">Основное содержание карточки</div>
<div slot="footer">Подвал карточки</div>
</app-card>
Множественные слоты предоставляют большую гибкость для управления
содержимым компонента. Например, можно задать значение по умолчанию для
каждого из слотов с помощью атрибута fallback, чтобы
компонент мог адаптироваться в зависимости от того, был ли передан
контент.
@Component({
tag: 'app-fallback-slot',
styleUrl: 'app-fallback-slot.css',
shadow: true
})
export class AppFallbackSlot {
render() {
return (
<div>
<header>
<slot name="header-content">По умолчанию: Заголовок</slot>
</header>
<main>
<slot name="main-content">По умолчанию: Основной контент</slot>
</main>
</div>
);
}
}
Если контент для слота не будет передан, вместо него отобразится текст по умолчанию.
Множественные слоты в Stencil открывают широкий спектр возможностей для разработки компонентов с гибким распределением контента. Использование именованных и неименованных слотов позволяет создавать переиспользуемые компоненты, которые можно легко адаптировать под различные сценарии. Механизм fallback контента помогает улучшить UX, предоставляя стандартное содержимое, если пользователь не передал свои данные.