Compound Components

Compound Components в Haunted

Подход compound components позволяет проектировать связанные элементы интерфейса как единое целое, сохраняя при этом высокую гибкость и выразительность API. В контексте библиотеки Haunted эта техника особенно удобна, поскольку Haunted соединяет функции, хуки и Web Components, обеспечивая чистую композицию без классовых наследований и тяжелой инфраструктуры.

Композитный компонент представляет сущность верхнего уровня (контейнер), которая содержит подкомпоненты (children) и управляет их поведением через контекст, пропсы и внутреннее состояние. Вместо передачи большого числа параметров каждому дочернему элементу, контейнер предоставляет согласованный интерфейс, а дочерние элементы используют этот интерфейс для координации.

Роль контекста в Haunted

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

Примерная структура:

  • Контейнер создает контекст.
  • Подкомпоненты используют контекст и реагируют на изменения состояния контейнера.
  • Логика состояния сосредоточена в одном месте, а визуальные элементы распределены между подкомпонентами.

Организация состояния

Контейнер обычно инкапсулирует состояние, которое определяет поведение всех дочерних компонентов. Для управления состоянием используются хуки useState, useMemo, useCallback и другие. Подкомпоненты не хранят критическое для модели приложение состояние, а играют роль “представителей” отдельного аспекта управления или отображения.

Ключевой момент: подкомпоненты могут быть переиспользуемыми, если не жёстко зависят от структуры контейнера. Для этого API контейнера должно быть минимальным, ясным и последовательным.

Коммуникация через события

Хотя контекст закрывает большинство задач синхронизации, иногда применяется событийная модель. Подкомпонент может генерировать пользовательские события (CustomEvent) для уведомления контейнера или соседних подкомпонентов. Haunted и Web Components естественным образом поддерживают подобный механизм через DOM-события, что снижает связность и повышает внеблочную переиспользуемость.

Применение для сложных интерфейсов

Техника compound components часто используется для:

  • форм и валидаторов;
  • раскрывающихся меню;
  • вкладок и панелей;
  • списков выбора и переключателей;
  • дружественных DSL для управления UI.

Такие интерфейсы требуют множества взаимозависимых элементов, и Haunted позволяет выражать их декларативно, без избыточных классов и стейт-машин.

Гибкость API

Хорошо спроектированный композитный компонент предоставляет понятный DSL. Например: контейнер объявляет структуру, а подкомпоненты внутри него определяются как слоты. Пользователь компонента может свободно комбинировать и переставлять подкомпоненты, не нарушая работу контейнера.

Пример принципов гибкого API:

  • Контейнер определяет контекст и состояние.
  • Подкомпоненты объявляют ожидания (подпишутся на контекст и, при необходимости, на события).
  • Кастомные элементы остаются независимыми от конкретного расположения.
  • Все части формируют единый UI-паттерн.

Рендеринг и производительность

Haunted использует lit-html для рендера, что дает диффинг и минимальные обновления. Композитные компоненты выигрывают от этого, поскольку изменения состояния контейнера не приводят к полной перерисовке всех подкомпонентов: перерисовываются только те, что используют изменившиеся данные.

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

Инкапсуляция через Web Components

Каждый подкомпонент Haunted может быть оформлен как Custom Element, что дает:

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

Композитный компонент при этом не обязан иметь собственный shadow DOM: иногда предпочтительнее использовать “светлый” DOM для гибкой композиции.

Отношение к шаблонным паттернам

Compound components в Haunted функционально напоминает подход из мира React, но адаптирован под Web Components. В отличие от HOC или mixin-подходов, здесь ключевой элемент — контекст и согласованный интерфейс. Нет необходимости расширять классы или создавать сложные структуры, что соответствует идеям функционального UI.

Отладка и тестирование

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

Практический вывод: compound components в Haunted оптимальны для UI, где множество элементов должны действовать сообща, оставаясь композиционно гибкими. Техника снижает связность, повышает переиспользуемость и улучшает читаемость структуры приложения.