Директива children

children — это специализированная директива в FAST Element, предназначенная для работы с коллекциями дочерних элементов внутри пользовательских веб-компонентов. Она обеспечивает динамическое отслеживание и реактивное управление дочерними элементами, создавая мост между DOM и моделью компонента.


Основные принципы работы

Директива children используется в классе элемента и связывается с селектором CSS, который определяет, какие дочерние элементы следует отслеживать. Она автоматически:

  • Подписывается на изменения DOM, включая добавление и удаление элементов.
  • Обновляет массив в компоненте при любых изменениях.
  • Позволяет указать тип элементов, которые ожидаются, обеспечивая типизацию и безопасность.

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

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

class MyList extends FASTElement {
  @children("li") listItems;
}

В этом примере listItems автоматически будет содержать массив всех <li> элементов, находящихся внутри компонента MyList. При добавлении нового <li> в DOM, массив обновляется без дополнительного кода.


Аргументы и параметры

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

  1. selector (строка) CSS-селектор для поиска дочерних элементов. Например: "li", "div.item", "my-component".

  2. options (объект) Позволяет задать дополнительные настройки:

    • property — имя свойства компонента, куда будут записываться элементы (по умолчанию совпадает с полем, аннотированным @children).
    • filter — функция фильтрации элементов.
    • adapter — функция для преобразования элементов перед помещением в массив.
    • waitFor — определяет, нужно ли ждать полного рендеринга дочерних элементов перед инициализацией.

Пример с фильтром и адаптером:

@children("li", {
  filter: node => node.textContent.trim() !== "",
  adapter: node => ({ content: node.textContent })
}) listItems;

В этом случае listItems будет содержать только элементы <li> с непустым текстом, а вместо элементов — объекты с полем content.


Реактивность и события

Массив, создаваемый children, является реактивным свойством. Любое изменение DOM автоматически вызывает обновление массива, что позволяет строить динамические интерфейсы без ручной подписки на MutationObserver.

Примеры сценариев:

  • Автоматическое обновление списка при добавлении элементов пользователем.
  • Доступ к дочерним компонентам для вызова их методов.
  • Сортировка, фильтрация или трансформация элементов в реальном времени.

При необходимости можно использовать обратные вызовы, реагирующие на изменения массива:

listItemsChanged(oldValue, newValue) {
  console.log("Старое значение:", oldValue);
  console.log("Новое значение:", newValue);
}

FAST Element автоматически вызывает метод с именем <property>Changed при каждом изменении массива.


Различия с children() и ChildObserver

Директива children является удобной оберткой над ChildObserver, предлагая декларативный способ работы. В то время как ChildObserver требует явной подписки и управления жизненным циклом:

this.listObserver = new ChildObserver(this, "li", records => {
  console.log("Обновление дочерних элементов:", records);
});
this.listObserver.observe();

@children упрощает эту задачу и автоматически интегрируется с реактивной системой FAST Element, что снижает вероятность ошибок и уменьшает объем кода.


Комбинирование с шаблонами

Директива children особенно полезна в сочетании с динамическими шаблонами:

const template = html<MyList>`
  <ul>
    <slot></slot>
  </ul>
`;

class MyList extends FASTElement {
  @children("li") listItems;

  logItems() {
    this.listItems.forEach(item => console.log(item.textContent));
  }
}

Здесь <slot> позволяет вставлять элементы из родительского контекста, а children автоматически отслеживает все <li> внутри компонента, даже если они приходят через слот.


Практические рекомендации

  • Использовать фильтры и адаптеры для приведения элементов к нужному виду до работы с ними в логике компонента.
  • Для сложных компонентов с большим количеством динамически создаваемых детей комбинировать children с методами жизненного цикла (connectedCallback, disconnectedCallback) для управления ресурсами.
  • Для элементов, создаваемых асинхронно, использовать параметр waitFor, чтобы избежать пустых массивов на этапе инициализации.

children обеспечивает полностью реактивное и декларативное управление дочерними элементами в FAST Element, сокращает количество кода, избавляет от прямого использования MutationObserver и делает компоненты более предсказуемыми и устойчивыми к изменениям DOM.