Polymer позволяет создавать кастомные
веб-компоненты, расширяя стандартные HTML-элементы и
обеспечивая переиспользуемость кода. Пользовательский элемент в Polymer
определяется как отдельный класс, который наследуется от базового класса
PolymerElement. Класс должен содержать шаблон
разметки и набор свойств, которые управляют
состоянием компонента.
Базовая структура элемента выглядит следующим образом:
import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
class MyElement extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: block;
color: #333;
}
</style>
<div>Привет, мир!</div>
`;
}
}
customElements.define('my-element', MyElement);
Ключевые моменты:
PolymerElement — базовый класс для всех компонентов
Polymer.static get template() — возвращает HTML-шаблон
элемента, включая стили.customElements.define() — регистрирует элемент в DOM,
связывая его имя с классом.Свойства в Polymer объявляются через статический геттер
properties. Каждое свойство может содержать тип, значение
по умолчанию, наблюдатели (observer) и возможность
отражения в атрибуты (reflectToAttribute).
Пример объявления свойств:
class MyElement extends PolymerElement {
static get properties() {
return {
name: {
type: String,
value: 'Пользователь',
observer: '_nameChanged'
},
count: {
type: Number,
value: 0,
reflectToAttribute: true
}
};
}
_nameChanged(newValue, oldValue) {
console.log(`Имя изменилось с ${oldValue} на ${newValue}`);
}
}
Особенности работы с свойствами:
reflectToAttribute.HTML-шаблон компонента определяется внутри `html```` литерала. Для Polymer характерно использование Shadow DOM, что обеспечивает изоляцию стилей и предотвращает конфликты с остальной частью страницы.
Пример сложного шаблона:
static get template() {
return html`
<style>
:host {
display: block;
font-family: sans-serif;
}
.header {
font-weight: bold;
margin-bottom: 10px;
}
.content {
padding: 10px;
border: 1px solid #ccc;
}
</style>
<div class="header">[[name]]</div>
<div class="content">
Счётчик: [[count]]
<button on-click="increment">Увеличить</button>
</div>
`;
}
increment() {
this.count += 1;
}
Важные моменты:
[[name]] и [[count]] — синтаксис
data binding для вывода значений свойств.on-click="increment" связывает событие с
методом компонента.Polymer позволяет расширять существующие элементы, создавая новые компоненты на основе базовых. Это достигается обычным наследованием классов:
class FancyButton extends PolymerElement {
static get template() {
return html`
<style>
button {
background-color: #4CAF50;
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
</style>
<button><slot></slot></button>
`;
}
}
customElements.define('fancy-button', FancyButton);
Особенности:
slot позволяет внедрять содержимое внутрь компонента,
поддерживая гибкую кастомизацию.Для взаимодействия с внешним миром элементы Polymer используют кастомные события. Это позволяет компоненту уведомлять родительский элемент о изменениях состояния.
Пример генерации события:
this.dispatchEvent(new CustomEvent('count-changed', {
detail: { count: this.count },
bubbles: true,
composed: true
}));
Особенности:
bubbles: true делает событие всплывающим по DOM.composed: true позволяет событию проходить через Shadow
DOM.<fancy-counter on-count-changed="handleCountChanged"></fancy-counter>
Этот подход к определению пользовательских элементов в Polymer обеспечивает гибкость, повторное использование и инкапсуляцию, позволяя создавать сложные интерфейсы с минимальными конфликтами стилей и логики.