Регистрация веб-компонентов в SkateJS основана на использовании стандартного механизма Custom Elements и дополняется удобными декораторами, вспомогательными функциями и системой рендеринга. Библиотека не прячет нативные API, а упрощает их применение и обеспечивает предсказуемый жизненный цикл.
Custom Elements требуют явного вызова
customElements.define. SkateJS инкапсулирует эту операцию и
связывает её с классом компонента. Минимальный фрагмент:
import { CustomElement } from 'skatejs';
class ButtonElement extends CustomElement {}
customElements.define('ui-button', ButtonElement);
Класс расширяет базовый CustomElement, предоставляющий
жизненный цикл, свойства и привязку шаблона. После регистрации тег
ui-button становится доступен в документе и может
использоваться как обычный HTML-элемент.
В проектах с Babel или TypeScript часто используется декоратор
@define. Он выполняет привязку
customElements.define к объявлению класса и сокращает
шаблонный код:
import { define, CustomElement } from 'skatejs';
@define('ui-card')
class CardElement extends CustomElement {}
Декоратор принимает имя тега, а при необходимости дополнительные параметры, например расширение существующего элемента. Такой способ делает регистрацию декларативной и хорошо сочетается с модульной структурой.
Имя должно содержать дефис, соответствовать спецификации Custom
Elements и не конфликтовать с существующими элементами. SkateJS не
вводит дополнительной логики проверки; корректность лежит на
разработчике. Распространённый подход — использовать префиксы:
ui-, app- или название пакета.
Попытка повторно определить один и тот же тег через
customElements.define вызовет исключение. SkateJS не
подавляет эту ошибку. В модульных системах рекомендуется проверять
существование компонента:
if (!customElements.get('ui-button')) {
customElements.define('ui-button', ButtonElement);
}
При использовании декораторов повторная регистрация обычно предотвращается структурой сборки, но в сложных проектах проверка остаётся актуальной.
Спецификация предусматривает расширение существующих тегов. SkateJS
поддерживает такое расширение через extends:
import { define, CustomElement } from 'skatejs';
@define('ui-link', { extends: 'a' })
class LinkElement extends CustomElement {}
Использование происходит через is:
<a is="ui-link" href="#">...</a>
Расширение встроенных элементов полезно для сохранения нативного поведения при добавлении логики. Поддержка зависит от браузера и может требовать полифиллов.
Регистрация компонента активирует стандартные хуки Custom Elements:
connectedCallback, disconnectedCallback,
attributeChangedCallback. SkateJS добавляет собственные
механизмы обновления и рендера, которые интегрируются в эти callbacks. В
результате каждый экземпляр компонента становится полностью автономным и
реагирует на изменения DOM.
После регистрации SkateJS синхронизирует объявленные свойства с атрибутами. Например:
import { define, CustomElement, prop } from 'skatejs';
@define('ui-counter')
class Counter extends CustomElement {
static props = {
value: prop.number({ default: 0 })
};
}
Регистрация делает свойство value доступным из DOM, а
изменение атрибута value вызывает обновление состояния и
рендера.
Регистрация компонента обычно происходит в модуле, чтобы
минимизировать загрязнение глобального пространства. SkateJS поощряет
стиль, при котором компонент определён и зарегистрирован в одном файле,
что облегчает контроль зависимостей. Импорт компонента автоматически
гарантирует его наличие в customElements.
В средах с серверным рендерингом или при ленивой загрузке компонентов регистрация может выполняться динамически. SkateJS не требует специального API для такой схемы: модуль просто импортируется при необходимости, после чего тег становится доступен. Это обеспечивает оптимизацию загрузки фронтенда и лучшее разделение кода.
Поскольку SkateJS опирается на нативный API, тестирование сводится к
созданию экземпляров через document.createElement и
проверке ожидаемого поведения. Регистрация обеспечивает наличие тега и
корректное создание экземпляров:
const el = document.createElement('ui-button');
document.body.appendChild(el);
В тестах отсутствует необходимость в специфичных для фреймворка моках.
Регистрация — точка входа для эволюции компонента в проекте. Одно и то же имя тега закрепляется за конкретным поведением, и изменение реализации происходит без влияния на потребителей тегов. Обратная совместимость обеспечивается классом и контрактом API, а SkateJS служит инструментом интеграции со стандартным DOM-окружением.
customElements.define.@define.Регистрация веб-компонентов в SkateJS даёт прямой доступ к спецификации, не добавляя избыточной магии и сохраняя прозрачность поведения.