Создание базового компонента

Определение компонента

Библиотека SkateJS предлагает декларативный и типобезопасный способ создания веб-компонентов поверх нативного Custom Elements API. Базовой сущностью является класс, расширяющий HTMLElement или Component, с определением пропертей, шаблона и логики жизненного цикла. При регистрации компонент становится доступен как новый HTML-тег.

Регистрация Custom Element

Ключевой шаг — объявление имени тега и связывание его с классом. SkateJS обеспечивает удобный хелпер define, позволяющий скрыть низкоуровневые детали и гарантировать корректное поведение при переинициализации в средах разработки.

Пример минимального определения без шаблона:

import { define, Component } from 'skatejs';

class HelloWorld extends Component {}

define('hello-world', HelloWorld);

После регистрации элемент hello-world воспринимается браузером как полноценный DOM-узел.

Параметры и свойства

Компоненты SkateJS используют систему пропертей с наблюдением за изменениями. Это снимает необходимость вручную отслеживать атрибуты и синхронизировать их с состоянием.

class HelloWorld extends Component {
  static props = {
    name: { attribute: true, default: 'Аноним' }
  };
}

Важные свойства:

  • attribute: true автоматически синхронизирует значение со значением атрибута в DOM.
  • default задаёт начальное состояние, если атрибут не указан.
  • При изменении значения вызывается обновление компонента.

Шаблон

Шаблон определяет структуру компонента. SkateJS поддерживает разные подходы: render с JSX/HTM либо renderer с использованием tagged templates.

С использованием функции render:

import { h } from 'skatejs';

class HelloWorld extends Component {
  static props = {
    name: { attribute: true, default: 'Аноним' }
  };

  render({ name }) {
    return h('span', null, `Привет, ${name}!`);
  }
}

define('hello-world', HelloWorld);

h является фабрикой виртуальных узлов, выполняющей роль аналога React.createElement, но без привязки к React. SkateJS самостоятельно обеспечивает диффинг и обновление DOM.

Работа с Shadow DOM

Для изоляции стилей и структуры можно включить Shadow DOM. Основной интерфейс — свойство shadowRoot. SkateJS использует его автоматически, если задать static shadowRoot = true.

class HelloShadow extends Component {
  static shadowRoot = true;

  render() {
    return 'Содержимое скрыто в Shadow DOM';
  }
}

Shadow DOM предотвращает утечки CSS, упрощает инкапсуляцию и позволяет использовать слоты:

render() {
  return h('slot');
}

Стилизация

SkateJS не навязывает строгую систему стилей. При использовании Shadow DOM возможно внедрение <style> в шаблон или подключение внешнего CSS.

render() {
  return [
    h('style', null, `
      span {
        color: 
        font-weight: bold;
      }
    `),
    h('span', null, 'Стилизованный текст')
  ];
}

При работе без Shadow DOM стили применяются глобально.

Жизненный цикл

SkateJS интегрируется с нативным жизненным циклом Custom Elements. Предоставляются методы:

  • connectedCallback — вызов при подключении к DOM.
  • disconnectedCallback — при удалении.
  • attributeChangedCallback — при изменении атрибута.
  • updatedCallback — после обновления пропертей.

Пример использования:

connectedCallback() {
  super.connectedCallback();
  console.log('Компонент вставлен в документ');
}

updatedCallback(prevProps, prevState) {
  console.log('Компонент обновлён');
}

super необходим при расширении Component, чтобы не нарушить внутренние механизмы обновлений.

События

Компонент может генерировать пользовательские события и подписываться на события DOM. Стандартный способ — dispatchEvent.

handleClick() {
  this.dispatchEvent(new CustomEvent('hello', {
    detail: { timestamp: Date.now() }
  }));
}

render() {
  return h('button', { onClick: () => this.handleClick() }, 'Нажми');
}

При подписке на события предпочтительно использовать синтаксис onEvent, который SkateJS обрабатывает автоматически.

Композиция компонентов

Компоненты SkateJS могут использоваться друг в друге, как обычные DOM-узлы. Благодаря инкапсуляции шаблона и свойств обеспечивается предсказуемое поведение и минимальное пересечение стилей. Это позволяет собирать сложные интерфейсы из независимых частей.

Основные преимущества базового подхода

  • прямое использование стандартов веб-компонентов;
  • отсутствие необходимости в стороннем фреймворке для рендеринга;
  • контроль над Shadow DOM и жизненным циклом;
  • простая декларация пропертей и атрибутов;
  • предсказуемая композиция.

Такой фундамент облегчает последующее расширение компонентов, интеграцию с системами состояния и подключение внешних инструментов сборки.