Слоты и проекция контента

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


Основы слотов

Слот — это место внутри компонента, куда можно передать произвольный контент из родительского компонента. По умолчанию слоты обозначаются тегом <slot></slot> внутри шаблона компонента:

<card>
  <slot></slot>
</card>

При использовании компонента можно передавать содержимое внутрь слота:

<card>
  <h1>Заголовок карточки</h1>
  <p>Описание карточки</p>
</card>

В этом случае весь внутренний HTML окажется в месте, где расположен <slot> внутри компонента card.


Именованные слоты

Для более сложных случаев можно использовать именованные слоты, чтобы контролировать, куда именно попадет конкретный фрагмент контента. Именованный слот задается через атрибут name:

<card>
  <slot name="header"></slot>
  <slot name="body"></slot>
</card>

В родительском компоненте или шаблоне можно направлять контент в конкретный слот:

<card>
  <h1 slot="header">Заголовок</h1>
  <p slot="body">Основное содержание</p>
</card>

Именованные слоты особенно полезны, когда требуется гибко управлять структурой компонента и размещением нескольких независимых блоков контента.


Содержимое по умолчанию

Если слот не получает внешнего содержимого, можно задать контент по умолчанию, который будет отображаться:

<card>
  <slot>Здесь будет стандартное содержимое</slot>
</card>

При отсутствии переданного контента <slot> выведет текст внутри себя.

Для именованных слотов также поддерживается контент по умолчанию:

<slot name="footer">Подвал по умолчанию</slot>

Динамическая проекция контента

Riot.js позволяет использовать динамический контент в слотах с помощью привязки данных. Например:

<card>
  <slot>{ dynamicContent }</slot>
</card>

Здесь переменная dynamicContent из компонента-родителя будет автоматически проецирована в слот. При изменении значения dynamicContent обновление произойдет автоматически благодаря реактивной системе Riot.js.


Слоты и вложенные компоненты

Проекция контента работает и для вложенных компонентов. Это значит, что один компонент может принимать слоты от родителя, а внутренние компоненты могут их использовать дальше:

<modal>
  <card>
    <h1 slot="header">Заголовок модального окна</h1>
    <p slot="body">Текст внутри модалки</p>
  </card>
</modal>

В таком случае компонент modal не должен заботиться о внутреннем содержимом card, но слоты позволят корректно разместить контент внутри всех вложенных компонентов.


Использование слотов с атрибутами и событиями

Слоты поддерживают передачу атрибутов и событий из родителя внутрь компонента. Например, можно передать обработчики клика или кастомные свойства:

<card>
  <button oncl ick={handleClick}>Нажать</button>
</card>

Событие onclick будет работать в контексте родительского компонента. Это позволяет строить более интерактивные и модульные интерфейсы.


Ограничения и рекомендации

  1. Проекция только одного уровня: Слоты работают для компонентов, но глубокая вложенность может потребовать дополнительной структуры или передачи данных через свойства.
  2. Не используйте сложные выражения внутри слота: Лучше передавать готовый контент или переменные для лучшей читаемости и поддерживаемости.
  3. Явное именование слотов упрощает поддержку больших проектов, где несколько компонентов принимают разные части контента.

Примеры практического применения

  • Карточки с заголовком, телом и подвалом: Именованные слоты позволяют полностью настраивать каждый блок без изменения шаблона компонента.
  • Модальные окна и диалоговые формы: Слоты помогают вставлять динамический контент и кнопки действия прямо из родительского компонента.
  • Списки и таблицы с настраиваемыми строками: Компоненты могут предоставлять общий контейнер, а строки или ячейки передаются через слоты, сохраняя гибкость отображения.

Механизм слотов и проекции контента в Riot.js обеспечивает высокую модульность, повторное использование компонентов и контроль над структурой интерфейса без дублирования кода и усложнения архитектуры. Он является фундаментальной частью современного подхода к построению реактивных компонентов.