Директива slotted

Директива slotted является ключевым инструментом при работе с веб-компонентами на базе FAST Element. Она позволяет получить доступ к содержимому, переданному в слот, и организовать взаимодействие между внутренней логикой компонента и внешними элементами, внедряемыми через слоты.


Принцип работы

Слоты — это специальные контейнеры в шаблоне компонента, которые позволяют пользователям компонента вставлять произвольный HTML или другие веб-компоненты. Директива slotted предоставляет реактивную привязку к элементам, размещённым внутри слота, и реагирует на изменения этого содержимого.

В отличие от обычного доступа через slot.assignedNodes() или slot.assignedElements(), slotted позволяет создавать реактивные свойства в классе компонента, автоматически отслеживая добавление и удаление элементов в слоте.


Синтаксис

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

class MyComponent extends FASTElement {
    @slotted() content;
}

MyComponent.define({
    name: 'my-component',
    template: html<MyComponent>`
        <slot></slot>
    `
});

Ключевые моменты синтаксиса:

  • @slotted() — декоратор, который используется для свойства класса.
  • content — имя свойства, в которое будут автоматически передаваться элементы слота.
  • Если слотов несколько, можно явно указать селектор слота:
@slotted('named-slot') namedContent;

Доступ к элементам слота

Свойство, помеченное @slotted(), может содержать:

  1. Массив элементов — когда в слот передаётся несколько элементов.
  2. Отслеживаемые изменения — добавление или удаление элементов в слот автоматически обновляет массив.

Пример использования:

class MyComponent extends FASTElement {
    @slotted() items;

    connectedCallback() {
        super.connectedCallback();
        console.log(this.items); // массив элементов, вставленных в слот
    }
}

Если элементы динамически добавляются после инициализации компонента, массив items будет автоматически обновлён, что позволяет легко реализовать реактивное взаимодействие с DOM.


Настройка поведения slotted

Декоратор @slotted принимает объект с опциями:

@slotted({
    filter: el => el.tagName === 'LI', // фильтрация элементов по условию
    flatten: true // объединяет все вложенные узлы в один массив
})
listItems;

Пояснения:

  • filter — функция фильтрации, возвращающая только нужные элементы.
  • flatten — если слот содержит вложенные узлы (например, <template> или <slot> внутри слота), эта опция разворачивает их в единый массив.

Эта функциональность особенно полезна для списков или динамически обновляемых наборов элементов, когда требуется наблюдать только определённые теги.


Работа с именованными слотами

Для компонентов с несколькими слотами можно использовать селекторы по имени:

@slotted('header') headerElements;
@slotted('footer') footerElements;

В шаблоне:

html<MyComponent>`
    <slot name="header"></slot>
    <div>Main content</div>
    <slot name="footer"></slot>
`

В этом случае headerElements будет содержать элементы, вставленные в <slot name="header">, а footerElements — элементы для <slot name="footer">.


Применение в динамических компонентах

Директива slotted отлично подходит для реактивных интерфейсов:

  • Реагирует на добавление или удаление элементов в реальном времени.
  • Позволяет реализовать автоматическое обновление списка элементов без дополнительной логики слежения за DOM.
  • Поддерживает фильтрацию и группировку элементов по критериям.

Пример динамического обновления списка:

class DynamicList extends FASTElement {
    @slotted({ filter: el => el.tagName === 'LI', flatten: true })
    listItems;

    listChanged() {
        console.log(`Количество элементов в списке: ${this.listItems.length}`);
    }
}

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


Ограничения и особенности

  • @slotted работает только с элементами, вставленными через <slot>. Контент, добавленный напрямую в шаблон компонента, не отслеживается этим декоратором.
  • Реактивность работает только для добавления/удаления элементов, не для изменения содержимого существующих элементов.
  • Для сложных структур с вложенными слотами рекомендуется использовать опцию flatten, иначе можно получить массив массивов.

Директива slotted обеспечивает мощный, реактивный способ взаимодействия с динамическим контентом в веб-компонентах на базе FAST Element, минимизируя необходимость ручного отслеживания DOM и упрощая работу с составными интерфейсами.