Render props

Render props — это мощный подход для управления рендерингом компонентов в FAST Element, позволяющий создавать высоко кастомизируемые и переиспользуемые элементы интерфейса. В основе лежит передача функции в качестве свойства компонента, которая отвечает за генерацию части DOM. Этот метод предоставляет полный контроль над тем, как именно отображаются внутренние элементы.

Основы использования render props

В FAST Element render props обычно реализуются через обычные свойства класса или наблюдаемые свойства (@observable), которые принимают функцию. Эта функция вызывается при рендеринге компонента, и её результат интегрируется в шаблон.

Пример:

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

const template = html<MyComponent>`
  <div>
    ${x => x.renderContent ? x.renderContent(x.data) : html``}
  </div>
`;

const styles = css`
  div {
    padding: 10px;
    border: 1px solid #ccc;
  }
`;

export class MyComponent extends FASTElement {
  @observable renderContent;
  @observable data;
}

MyComponent.define({
  name: "my-component",
  template,
  styles,
});

В этом примере свойство renderContent — функция, которая получает данные data и возвращает шаблон для рендеринга. Такой подход позволяет компоненту быть полностью независимым от конкретной разметки, делегируя контроль родителю.

Передача параметров в render props

Функция render props может принимать произвольные аргументы, что делает её гибкой для различных сценариев. Обычно передаются:

  • Данные, которые необходимо визуализировать.
  • Методы компонента, например, для обработки событий.
  • Контекст состояния или конфигурации.

Пример с параметрами:

const template = html<MyList>`
  <ul>
    ${x => x.renderItem 
      ? x.items.map(item => x.renderItem(item, x.onSelect)) 
      : x.items.map(item => html`<li>${item}</li>`)}
  </ul>
`;

export class MyList extends FASTElement {
  @observable items = [];
  @observable renderItem;
  
  onSelect(item) {
    console.log("Selected:", item);
  }
}

Здесь renderItem получает элемент массива и функцию onSelect. Это позволяет родителю компонента полностью контролировать рендер каждого элемента списка.

Динамическая замена шаблона

Render props удобны для динамической подстановки шаблонов. Это особенно полезно, когда нужно менять визуализацию без изменения логики компонента.

myList.renderItem = (item) => html`
  <li style="color: ${item.active ? 'green' : 'gray'}">
    ${item.name}
  </li>
`;

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

Взаимодействие с FAST шаблонами

Render props интегрируются с FAST Element на уровне шаблонов. Функция возвращает либо:

  • html шаблон, создаваемый через html из FAST Element.
  • Пустой шаблон `html```, если нужно условно ничего не рендерить.
  • Фрагменты DOM, включая компоненты FAST или стандартные элементы.

Важно учитывать реактивность. Любые наблюдаемые свойства, использованные внутри функции render props, автоматически инициируют повторный рендер при изменении значения.

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

Render props легко комбинируются с событиями и локальным состоянием компонента. Пример:

myList.renderItem = (item, onSelect) => html`
  <li @click=${() => onSelect(item)}>
    ${item.name}
  </li>
`;

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

Практические сценарии

  • Списки и таблицы: Render props дают полный контроль над рендерингом каждой строки, включая условное форматирование, кнопки действий и кастомные компоненты.
  • UI библиотеки: Компоненты с render props становятся универсальными, так как внешний код может определять внешний вид без изменения внутренней логики.
  • Динамические формы: Каждое поле формы можно рендерить через функцию, передавая метаданные и обработчики событий.

Важные моменты

  1. Реактивность: Используемые в render props наблюдаемые свойства автоматически обновляют DOM.
  2. Производительность: Render props вызываются при каждом ререндере компонента, поэтому внутри них не стоит выполнять тяжёлые вычисления.
  3. Чистота шаблона: Рекомендуется, чтобы render props возвращали только шаблон. Логику обработки лучше оставлять в методах компонента.

Render props в FAST Element позволяют создавать гибкие, расширяемые и полностью настраиваемые компоненты, сохраняя преимущества реактивного рендеринга и реактивных шаблонов библиотеки. Они превращают компонент в мощный каркас, в который можно подставить любое визуальное представление и логику событий, не меняя внутреннюю структуру.