Множественные слоты

FAST Element предоставляет мощный механизм работы с шаблонами и слотами, позволяя создавать сложные компоненты с гибкой структурой. Слоты — это область в шаблоне компонента, куда можно вставлять внешнее содержимое. Поддержка множественных слотов расширяет возможности кастомизации компонентов, позволяя разработчику точно определять, куда попадает каждый кусок контента.

Определение нескольких слотов

Для объявления нескольких слотов используется атрибут name у тега <slot>. По умолчанию, если слот не имеет имени, он считается дефолтным. Пример:

import { FASTElement, html, css } from "@microsoft/fast-element";

const template = html`
  <div class="header">
    <slot name="header"></slot>
  </div>
  <div class="content">
    <slot></slot>
  </div>
  <div class="footer">
    <slot name="footer"></slot>
  </div>
`;

const styles = css`
  .header { font-weight: bold; padding: 8px; background: #f0f0f0; }
  .content { padding: 8px; }
  .footer { font-size: smaller; color: #888; padding: 8px; }
`;

export class MultiSlotComponent extends FASTElement {
}

MultiSlotComponent.define({
  name: "multi-slot-component",
  template,
  styles
});

В этом примере компонент имеет три слота:

  • header — именованный слот для заголовка,
  • дефолтный слот для основного содержимого,
  • footer — именованный слот для подвала.

Использование именованных слотов

Чтобы наполнить именованные слоты контентом, в HTML необходимо указать атрибут slot у вставляемых элементов:

<multi-slot-component>
  <div slot="header">Заголовок компонента</div>
  <p>Основное содержимое компонента</p>
  <div slot="footer">Подвал компонента</div>
</multi-slot-component>

Элементы будут распределены по соответствующим слотам. Элементы без атрибута slot попадут в дефолтный слот.

Динамическое управление слотами

FAST Element позволяет наблюдать за содержимым слотов с помощью события slotchange. Это особенно важно для динамически добавляемого контента.

const contentSlot = this.shadowRoot.querySelector('slot:not([name])');
contentSlot.addEventListener('slotchange', (event) => {
  const assignedElements = event.target.assignedElements();
  console.log('Контент дефолтного слота изменился', assignedElements);
});

const headerSlot = this.shadowRoot.querySelector('slot[name="header"]');
headerSlot.addEventListener('slotchange', (event) => {
  const assignedElements = event.target.assignedElements();
  console.log('Контент заголовка изменился', assignedElements);
});

Метод assignedElements() возвращает массив элементов, которые вставлены в слот, что позволяет реагировать на изменения и управлять содержимым программно.

Стилизация слотов

Слоты сами по себе не отображают стили, но их можно стилизовать через контейнеры в шаблоне или с помощью селектора ::slotted(). Пример:

::slotted([slot="header"]) {
  color: white;
  background-color: #0078d7;
  padding: 4px 8px;
  border-radius: 4px;
}

::slotted([slot="footer"]) {
  font-style: italic;
  color: #666;
}

::slotted(p) {
  line-height: 1.5;
}

Селектор ::slotted() применяет стили только к непосредственным потомкам слота, что предотвращает непреднамеренное наследование вложенных элементов.

Вложенные слоты

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

<outer-component>
  <inner-component slot="header">
    <span slot="inner-header">Вложенный заголовок</span>
  </inner-component>
  <p>Основное содержимое</p>
</outer-component>

В этом примере внешний слот header получает компонент inner-component, который внутри управляет своим собственным именованным слотом inner-header.

Рекомендации по организации множественных слотов

  • Именовать все слоты для ясного назначения контента.
  • Дефолтный слот использовать только для основного или наименее критичного содержимого.
  • Использовать событие slotchange для динамических компонентов.
  • Строго контролировать стили через контейнеры и ::slotted().
  • Для вложенных компонентов явно указывать слоты, чтобы избежать “потерянного” контента.

Практические примеры

  1. Карточка с заголовком, изображением и подвалом:
<card-component>
  <h2 slot="header">Заголовок карточки</h2>
  <img src="image.jpg" alt="Превью">
  <div slot="footer">Автор: Иванов</div>
</card-component>
  1. Модальное окно с динамическим контентом:
<modal-dialog>
  <h3 slot="header">Предупреждение</h3>
  <p>Вы действительно хотите удалить запись?</p>
  <div slot="footer">
    <button>Отмена</button>
    <button>Удалить</button>
  </div>
</modal-dialog>

Такое разделение слотов позволяет компоненту оставаться гибким, а структуре — логичной и легко расширяемой.

Множественные слоты в FAST Element обеспечивают мощный и чистый способ управления структурой и содержимым компонента, что особенно важно при создании комплексных интерфейсов с повторно используемыми элементами.