Custom Elements API является фундаментом для создания переиспользуемых компонентов в Polymer. Он позволяет определять собственные HTML-теги с уникальным поведением, структурой и стилями, интегрированными в DOM.
Для создания нового элемента используется метод
customElements.define(tagName, class). Класс должен
наследоваться от HTMLElement или других встроенных
элементов через extends.
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `<p>Привет, Polymer!</p>`;
}
}
customElements.define('my-element', MyElement);
Ключевые моменты:
tagName должен содержать дефис (-), иначе
элемент не будет признан пользовательским.attachShadow({mode: 'open'}) создаёт Shadow DOM,
обеспечивая инкапсуляцию стилей и структуры.Polymer расширяет стандарт Custom Elements, обеспечивая удобную
работу с реактивными свойствами через properties. Свойства
могут быть связаны с атрибутами, что позволяет синхронизировать
состояние элемента с DOM.
class MyElement extends HTMLElement {
static get observedAttributes() {
return ['name'];
}
get name() {
return this._name;
}
set name(value) {
this._name = value;
this.render();
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (attrName === 'name') {
this.name = newVal;
}
}
render() {
this.shadowRoot.innerHTML = `<p>Привет, ${this.name}!</p>`;
}
}
customElements.define('my-element', MyElement);
Особенности:
observedAttributes указывает, за какими атрибутами
следует следить.attributeChangedCallback вызывается при изменении
атрибута в DOM.Custom Elements обладают рядом методов жизненного цикла:
constructor() – инициализация элемента.connectedCallback() – вызывается при добавлении
элемента в DOM.disconnectedCallback() – вызывается при удалении
элемента из DOM.adoptedCallback() – вызывается при переносе элемента в
другой документ.attributeChangedCallback(name, oldValue, newValue) –
реагирует на изменения атрибутов.Пример использования:
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.render();
}
disconnectedCallback() {
console.log('Элемент удалён из DOM');
}
render() {
this.shadowRoot.innerHTML = `<p>Элемент подключён к DOM</p>`;
}
}
customElements.define('my-element', MyElement);
Shadow DOM обеспечивает скрытую структуру внутри компонента. Это позволяет избежать конфликта стилей с внешней страницей и создавать изолированные элементы.
attachShadow({mode: 'open'}) создаёт открытый Shadow
DOM, доступный через shadowRoot.attachShadow({mode: 'closed'}) создаёт закрытый Shadow
DOM, недоступный извне.Пример использования стилей в Shadow DOM:
this.shadowRoot.innerHTML = `
<style>
p {
color: blue;
font-weight: bold;
}
</style>
<p>Текст в изолированном стиле</p>
`;
Custom Elements могут наследоваться от встроенных HTML-тегов, что позволяет расширять их функциональность:
class MyButton extends HTMLButtonElement {
constructor() {
super();
this.addEventListener('click', () => alert('Нажато!'));
}
}
customElements.define('my-button', MyButton, { extends: 'button' });
Использование:
<button is="my-button">Кнопка</button>
Polymer предоставляет удобный синтаксис для декларативного описания компонентов и их реактивного поведения. Компоненты Polymer используют Custom Elements API как основу и добавляют:
properties для реактивного состояния.template для декларативного рендеринга.dom-bind и dom-repeat для привязки данных
и повторяющихся элементов.Пример простого Polymer-компонента:
import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
class MyPolymerElement extends PolymerElement {
static get properties() {
return {
name: { type: String, value: 'Polymer' }
};
}
static get template() {
return html`
<p>Привет, [[name]]!</p>
`;
}
}
customElements.define('my-polymer-element', MyPolymerElement);
Ключевые моменты:
[[property]] обеспечивает реактивное
связывание данных.Custom Elements позволяют генерировать и обрабатывать собственные
события. Polymer расширяет это через notify и декларативные
слушатели.
this.dispatchEvent(new CustomEvent('name-changed', {
detail: { value: this.name },
bubbles: true,
composed: true
}));
bubbles: true позволяет событию подниматься вверх по
DOM.composed: true позволяет событию проходить через Shadow
DOM.Custom Elements API является основой компонентного подхода в Polymer, обеспечивая мощную инкапсуляцию, реактивное обновление и расширяемость встроенных HTML-элементов. В сочетании с декларативной привязкой данных и шаблонами Polymer создаются гибкие и переиспользуемые веб-компоненты.