Фреймворк Polymer предоставляет мощный механизм для создания веб-компонентов с возможностью гибкой проекции контента. Основной инструмент для этого — слоты. С их помощью можно управлять тем, как внешний контент вставляется внутрь компонентов, сохраняя инкапсуляцию и повторное использование элементов.
Слот — это место внутри веб-компонента, куда может быть вставлен
внешний контент. В Polymer слоты реализуются с помощью элемента
<slot>. Любой элемент, помещённый в компонент с
указанием слота, автоматически проецируется в соответствующее место.
Простейший пример:
<my-card>
<h1 slot="title">Заголовок карточки</h1>
<p>Описание карточки</p>
</my-card>
Компонент my-card может быть описан так:
import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
class MyCard extends PolymerElement {
static get template() {
return html`
<div class="card">
<header>
<slot name="title"></slot>
</header>
<main>
<slot></slot>
</main>
</div>
`;
}
}
customElements.define('my-card', MyCard);
Здесь:
<slot name="title"></slot> проецирует
содержимое с атрибутом slot="title".<slot></slot> без имени — это
дефолтный слот, куда попадает контент без указания
имени.Дефолтные слоты Используются для проекции контента без явного указания имени.
<slot></slot>
Вставленный в компонент элемент без атрибута slot
попадёт именно сюда.
Именованные слоты Позволяют точно управлять размещением контента.
<slot name="footer"></slot>
Контент проецируется только если у него задано
slot="footer".
<slot>
<p>Содержимое по умолчанию</p>
</slot>
Polymer предоставляет API для работы с содержимым слотов:
const slot = this.shadowRoot.querySelector('slot[name="title"]');
const assignedNodes = slot.assignedNodes({flatten: true});
Метод assignedNodes() возвращает все узлы, которые
проецируются в слот, включая текстовые и элементные узлы. Параметр
{flatten: true} учитывает вложенные слоты.
С помощью этого механизма можно:
slotchange):slot.addEventListener('slotchange', (e) => {
console.log('Содержимое слота изменено', slot.assignedNodes());
});
Слоты позволяют строить многоуровневые компоненты, где один компонент проецирует контент другого. Пример:
<parent-component>
<child-component slot="header">
<p>Заголовок ребенка</p>
</child-component>
</parent-component>
В parent-component можно иметь слот header,
а child-component внутри тоже может использовать свои
слоты. Polymer корректно распределяет контент, сохраняя структуру
DOM.
slotchange полезна для реактивного
обновления состояния компонента при изменении проецируемого
контента.Карточка с заголовком и подвалом:
<my-card>
<h1 slot="title">Новости дня</h1>
<p>Главные события сегодня...</p>
<footer slot="footer">Источник: news.com</footer>
</my-card>
Шаблон компонента:
class MyCard extends PolymerElement {
static get template() {
return html`
<div class="card">
<header><slot name="title"></slot></header>
<main><slot></slot></main>
<footer><slot name="footer">Подвал по умолчанию</slot></footer>
</div>
`;
}
}
Слоты обеспечивают гибкость и расширяемость компонентов, что особенно важно для повторного использования UI-элементов и создания настраиваемых библиотек интерфейса.
С помощью слотов Polymer реализует концепцию content projection, позволяя разработчикам создавать сложные, динамические интерфейсы без нарушения инкапсуляции компонентов. Это один из ключевых механизмов, обеспечивающих гибкость веб-компонентов.