Техника render props через слоты в библиотеке Haunted позволяет динамически передавать разметку и логику дочерним компонентам, сохраняя контроль за структурой и поведением на уровне родителя. Это делает композицию компонентов более гибкой и естественной для веб-компонентов.
Render props адаптируются к веб-компонентам через HTML-слоты. Haunted не модифицирует специфику слотов, а лишь облегчает управление состоянием и реактивностью. В результате слоты становятся аналогом функций-рендеров, характерных для React-подхода.
Ключевой момент: слот отвечает за передачу части разметки, а Haunted-компонент — за реактивное состояние и синхронизацию данных.
Компонент объявляется как классический Haunted-компонент на основе
component и функции-хука. Внутри шаблона используется
<slot> для внедрения произвольного контента.
import { component, useState, html } from 'haunted';
function Panel() {
const [open, setOpen] = useState(true);
return html`
<section class="${open ? 'open' : 'closed'}">
<header>
<button @click=${() => setOpen(o => !o)}>
${open ? 'Скрыть' : 'Показать'}
</button>
</header>
<div class="content">
<slot></slot>
</div>
</section>
`;
}
customElements.define('x-panel', component(Panel));
Слот в данном случае выступает как render prop: родительский компонент задаёт логику, а внешний код передаёт разметку для отображения.
Для более детальной передачи частей разметки используются именованные слоты. Они позволяют распределять контент по зонам интерфейса и усиливают аналогию с render props, передающими несколько функций.
function Card() {
return html`
<article class="card">
<header><slot name="title"></slot></header>
<section><slot name="body"></slot></section>
<footer><slot name="actions"></slot></footer>
</article>
`;
}
customElements.define('x-card', component(Card));
Важный аспект: Haunted при этом не внедряет собственные протоколы передачи данных; слоты соответствуют стандарту Custom Elements и работают независимо от фреймворка.
Render props через слоты раскрываются особенно полно при наличии состояния в компоненте. Haunted предоставляет набор хуков, аналогичных React-хукам. Таким образом появляется возможность управлять отображением переданного через слот контента.
function Tabs() {
const [active, setActive] = useState('one');
return html`
<nav>
<button @click=${() => setActive('one')}>Первая</button>
<button @click=${() => setActive('two')}>Вторая</button>
</nav>
<section>
${active === 'one'
? html`<slot name="one"></slot>`
: html`<slot name="two"></slot>`}
</section>
`;
}
customElements.define('x-tabs', component(Tabs));
Слоты в данном примере эмулируют динамический выбор рендера, что полностью соответствует render props-паттерну.
Стандартные слоты не позволяют напрямую передавать параметры внутрь контента. Для передачи данных используется механизм событий либо отражение атрибутов на уровне веб-компонента. Render props через слоты подразумевают передачу не только структуры, но и контекста, поэтому практикуется следующий подход:
1. Пробрасывание состояния через атрибуты
Компонент обновляет атрибуты, а вложенная разметка реагирует через CSS или JavaScript.
2. Использование кастомных событий
Компонент диспатчит событие, а внешний код принимает и использует его для рендера. В этом случае слот выступает как канал рендера, а событие — как канал данных.
Shadow DOM влияет на применимость стилей, что является особенностью render props через слоты в веб-компонентах. Содержимое слота рендерится вне shadow root, а значит наследует окружение родительского документа. Такой механизм выгоден для render props, поскольку контент может быть стилизован независимо от внутренней структуры компонента.
Ключевое следствие: компонент управляет структурой и логикой, а внешний контент управляет стилями и визуальным слоем.
Render props через слоты в Haunted создают основу для композиции без сложного проп-дриллинга. Можно строить компоненты более высокого порядка: один компонент управляет логикой, а другой — отображением, при этом связь обеспечивается слотами.
Композиция особенно выразительна при построении UI-библиотек на веб-компонентах. Haunted обеспечивает минимальный уровень абстракции, позволяя сосредоточиться на React-подобной реактивности без существенного усложнения.
В подходе React render props — это функции, возвращающие JSX. В веб-компонентах те же идеи реализуются через слоты и Shadow DOM. Haunted дополняет архитектуру реактивностью и хуками, облегчая создание компонентов со сложной внутренней логикой без отказа от нативных механизмов браузера.
Сходство:
Отличие:
Render props через слоты применяются в компонентах:
Этот подход особенно ценен, когда структура компонента фиксирована, а контент может варьироваться.
Render props через слоты в Haunted — способ привнести композиционные практики современных фреймворков в мир веб-компонентов, используя нативные стандарты HTML. Haunted не нарушает семантики слотов и не изменяет модель DOM, что обеспечивает совместимость, предсказуемость и расширяемость.