Haunted — это библиотека для создания веб-компонентов на базе функционального подхода и хуков, вдохновлённая React, но работающая на чистом Web Components API. Одним из ключевых механизмов для организации и переиспользования контента в компонентах являются слоты и проекция контента. Они позволяют вставлять динамический HTML внутрь компонента, обеспечивая гибкость в композиции интерфейсов.
Слот — это специальный маркер внутри шаблона компонента, который указывает, куда будет вставлен внешний контент. В Haunted слоты работают так же, как в стандартных Web Components.
import { component, html, useState } from 'haunted';
function Card() {
return html`
<div class="card">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
`;
}
customElements.define('my-card', component(Card));
<slot> без имени принимает неименованный
контент.<slot name="header"> и
<slot name="footer"> принимают именованные
фрагменты, передаваемые через атрибут slot.Пример использования:
<my-card>
<h1 slot="header">Заголовок карточки</h1>
<p>Основной контент карточки</p>
<small slot="footer">Подпись</small>
</my-card>
В этом примере:
header.footer.Haunted позволяет использовать состояния и хуки для динамического обновления содержимого слотов. Это особенно удобно для компонентов, где внешний контент может меняться в зависимости от данных.
function ToggleCard({ initialText }) {
const [show, setShow] = useState(true);
return html`
<div class="toggle-card">
<button @click=${() => setShow(!show)}>Переключить</button>
<div>
${show ? html`<slot>${initialText}</slot>` : html`<slot>Контент скрыт</slot>`}
</div>
</div>
`;
}
customElements.define('toggle-card', component(ToggleCard));
Здесь <slot> динамически меняет отображаемое
содержимое на основе состояния show. Это демонстрирует, что
слоты в Haunted интегрируются с реактивной моделью данных через
хуки.
Проекция контента (content projection) — это процесс передачи HTML или компонентов внутрь другого компонента через слоты. Haunted полностью наследует этот механизм из Web Components. Проекция позволяет компоненту оставаться универсальным и не зависеть от конкретного внутреннего контента.
Ключевые особенности:
<slot>.Пример fallback контента:
function Alert() {
return html`
<div class="alert">
<slot>Внимание! Нет содержимого.</slot>
</div>
`;
}
customElements.define('my-alert', component(Alert));
Если пользователь не передаст содержимое в
<my-alert>, отобразится сообщение по умолчанию.
Haunted позволяет создавать вложенные компоненты с слотами, что открывает возможности для построения сложных UI.
function Modal() {
return html`
<div class="modal">
<div class="modal-header">
<slot name="header">Заголовок по умолчанию</slot>
</div>
<div class="modal-body">
<slot></slot>
</div>
<div class="modal-footer">
<slot name="footer"></slot>
</div>
</div>
`;
}
customElements.define('my-modal', component(Modal));
Использование:
<my-modal>
<h2 slot="header">Диалог</h2>
<p>Контент диалога</p>
<button slot="footer">Закрыть</button>
</my-modal>
Такой подход позволяет строить гибкие и переиспользуемые компоненты с полностью настраиваемым содержимым.
В Haunted слоты могут быть связаны с реактивными хуками для управления отображением:
function TabContent({ activeTab }) {
return html`
<div class="tabs">
<slot name=${activeTab}></slot>
</div>
`;
}
customElements.define('tab-content', component(TabContent));
В этом примере через динамическое имя слота можно
переключать отображаемое содержимое в зависимости от состояния
activeTab. Это демонстрирует, что Haunted не ограничивается
статической проекцией, а полностью интегрируется с реактивной моделью
данных.
Слоты и проекция контента в Haunted — фундаментальные инструменты для построения модульных, переиспользуемых и реактивных компонентов. Они обеспечивают максимальную гибкость при структурировании интерфейсов и позволяют разделять логику компонента и его внешний контент без потери производительности.