Polymer — это библиотека для создания веб-компонентов, ориентированная на повторное использование элементов интерфейса и их композицию. Композиция компонентов позволяет строить сложные интерфейсы из небольших, независимых элементов, повышая модульность и упрощая поддержку кода.
В Polymer каждый компонент — это отдельный класс, наследующийся от
PolymerElement, с собственным шаблоном
(template) и стилями. Композиция строится на принципе
включения одного компонента в другой через HTML-разметку.
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
import './child-element.js';
class ParentElement extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: block;
padding: 16px;
border: 1px solid #ccc;
}
</style>
<child-element></child-element>
<p>Дополнительный контент родителя</p>
`;
}
}
customElements.define('parent-element', ParentElement);
Ключевой момент: дочерние элементы автоматически становятся частью DOM родителя, что позволяет управлять их поведением и стилями.
Polymer использует Shadow DOM, чтобы изолировать стили и структуру компонента. При композиции необходимо учитывать:
::slotted).<slot>
позволяет родителю вставлять динамический контент внутрь
компонента.Пример использования слотов:
class CardElement extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: block;
border: 1px solid #aaa;
padding: 12px;
border-radius: 4px;
}
::slotted(*) {
margin: 4px 0;
}
</style>
<div>
<slot></slot>
</div>
`;
}
}
customElements.define('card-element', CardElement);
Теперь родительский компонент может вставлять произвольный контент в карточку:
<card-element>
<p>Текст внутри карточки</p>
<button>Кнопка</button>
</card-element>
Компоненты могут взаимодействовать через свойства и события. Polymer поддерживает двустороннюю привязку данных и механизм событий:
dispatchEvent.Пример передачи данных и события:
class CounterElement extends PolymerElement {
static get properties() {
return {
count: { type: Number, value: 0 }
};
}
increment() {
this.count += 1;
this.dispatchEvent(new CustomEvent('count-changed', {
detail: { count: this.count },
bubbles: true,
composed: true
}));
}
static get template() {
return html`
<button on-click="increment">Увеличить</button>
<p>Текущее значение: [[count]]</p>
`;
}
}
customElements.define('counter-element', CounterElement);
Родительский компонент может слушать событие
count-changed и реагировать на изменения.
Polymer позволяет создавать компоненты динамически через JavaScript, что особенно полезно для списков или интерфейсов с изменяющимся составом элементов:
const listContainer = document.querySelector('#list');
for (let i = 0; i < 5; i++) {
const item = document.createElement('child-element');
item.setAttribute('data-index', i);
listContainer.appendChild(item);
}
Такой подход обеспечивает гибкость композиции, позволяя управлять компонентами на лету.
Polymer поддерживает шаблоны <dom-repeat> для
генерации компонентов на основе массивов:
class ItemList extends PolymerElement {
static get properties() {
return {
items: { type: Array, value: () => ['Элемент 1', 'Элемент 2', 'Элемент 3'] }
};
}
static get template() {
return html`
<template is="dom-repeat" items="[[items]]">
<child-element item="[[item]]"></child-element>
</template>
`;
}
}
customElements.define('item-list', ItemList);
Преимущество: автоматически создаются и удаляются дочерние компоненты при изменении массива, сохраняя синхронизацию с данными.
Для управления стилями вложенных компонентов применяются следующие подходы:
::slotted.<style include="shared-styles">.<style>
:host {
--primary-color: #3498db;
}
child-element {
color: var(--primary-color);
}
</style>
Комплексное использование этих механизмов делает Polymer мощным инструментом для создания модульных и легко поддерживаемых веб-приложений.