Монорепозитории

SkateJS — это библиотека для создания веб-компонентов, ориентированная на декларативный и реактивный подход. Она предоставляет минимальный, но мощный API для определения компонентов, управления их состоянием и взаимодействия с DOM. В основе SkateJS лежит концепция реактивных свойств и жизненного цикла компонента, что позволяет строить сложные интерфейсы без избыточного кода.

Компоненты в SkateJS создаются с помощью функции define и наследования от базового класса Component. Каждый компонент может содержать:

  • Свойства (props) — реактивные данные компонента.
  • Шаблон рендеринга (render) — возвращает DOM-структуру компонента.
  • Методы жизненного циклаconnectedCallback, disconnectedCallback, UPDATEd, обеспечивающие контроль над поведением компонента.

Пример минимального компонента:

import { define, Component, h } from 'skatejs';

class MyButton extends Component {
  static props = {
    label: String
  };

  render() {
    return <button>{this.label}</button>;
  }
}

define(MyButton);

В этом примере свойство label автоматически связывается с отображением в DOM. Любое изменение свойства приводит к перерендеру компонента.


Реактивные свойства и их типизация

SkateJS использует декларативную модель свойств. Для каждого свойства можно указать:

  • Тип (String, Number, Boolean, Object, Array).
  • Значение по умолчанию через функцию default.
  • Кастомные обработчики изменения свойства (set).

Пример:

static props = {
  count: {
    type: Number,
    default: 0,
    se t(element, oldValue, newValue) {
      console.log(`Старое значение: ${oldValue}, новое: ${newValue}`);
    }
  }
};

Важно, что изменения свойств автоматически запускают реактивный рендеринг, поэтому компонент всегда синхронизирован с состоянием.


Жизненный цикл компонента

SkateJS предоставляет несколько ключевых методов жизненного цикла:

  • connectedCallback — вызывается при вставке компонента в DOM. Используется для инициализации сторонних библиотек или подписок.
  • disconnectedCallback — вызывается при удалении компонента из DOM. Рекомендуется использовать для очистки ресурсов.
  • updated — вызывается после изменения любого свойства. Можно получить список изменившихся свойств.

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

class MyInput extends Component {
  static props = {
    value: String
  };

  connectedCallback() {
    console.log('Компонент добавлен в DOM');
  }

  disconnectedCallback() {
    console.log('Компонент удален из DOM');
  }

  updated(changedProps) {
    if (changedProps.has('value')) {
      console.log(`Значение изменилось: ${this.value}`);
    }
  }

  render() {
    return <input value={this.value} />;
  }
}

define(MyInput);

Шаблонизация и JSX

SkateJS интегрируется с JSX и гиперфункцией h, что позволяет описывать DOM в декларативном стиле. Компоненты могут содержать условные конструкции, списки элементов и вложенные компоненты.

Пример условного рендеринга:

render() {
  return (
    <div>
      {this.items.length > 0
        ? this.items.map(item => <li>{item}</li>)
        : <p>Список пуст</p>}
    </div>
  );
}

Использование JSX упрощает создание сложной структуры DOM и делает код более читаемым и поддерживаемым.


События и пользовательские события

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

Пример:

this.dispatchEvent(new CustomEvent('item-selected', {
  detail: { id: 42 },
  bubbles: true,
  composed: true
}));

Параметры bubbles и composed позволяют событию проходить через Shadow DOM и родительские элементы, обеспечивая гибкое взаимодействие.


Работа с Shadow DOM

SkateJS по умолчанию поддерживает Shadow DOM. Использование Shadow DOM изолирует стили и предотвращает конфликты с глобальными CSS.

Пример компонента с Shadow DOM:

class MyCard extends Component {
  static shadow = true;

  render() {
    return (
      <div class="card">
        <h2>{this.title}</h2>
      </div>
    );
  }
}

define(MyCard);

Стили можно включать внутри Shadow DOM через обычный <style> или импортировать CSS-модули.


Интеграция с монорепозиториями

При работе с монорепозиториями SkateJS компоненты можно организовать в отдельные пакеты. Каждый пакет может содержать:

  • Компоненты
  • Стили и шаблоны
  • Утилиты и хелперы

Структура монорепозитория часто выглядит так:

packages/
  button/
    src/
      Button.js
      Button.css
    package.json
  input/
    src/
      Input.js
      Input.css
    package.json

Преимущества такого подхода:

  • Повторное использование компонентов в разных проектах.
  • Изоляция зависимостей и тестов.
  • Гибкая версияция отдельных компонентов.

Для публикации пакета используется стандартный механизм npm, а компоненты можно подключать через обычный import:

import { MyButton } from '@company/button';

В больших проектах рекомендуется использовать сборщики, поддерживающие ES-модули, например Rollup или Vite, чтобы минимизировать размер и ускорить загрузку.


Оптимизация рендеринга

SkateJS оптимизирует перерендеринг компонентов: изменения свойств вызывают обновление только тех частей DOM, которые зависят от измененных свойств. Для сложных компонентов можно использовать методы shouldUpdate и мемоизацию.

Пример:

shouldUpdate(changedProps) {
  return changedProps.has('importantProp');
}

Это предотвращает лишние обновления и повышает производительность приложений с большим количеством компонентов.


Заключение по возможностям SkateJS

SkateJS объединяет реактивность, декларативность и модульность, что делает библиотеку удобной для построения современных веб-компонентов. Она поддерживает Shadow DOM, интеграцию с JSX, реактивные свойства и жизненный цикл, а также легко масштабируется в монорепозиториях, обеспечивая высокую переиспользуемость и контроль версий компонентов.