Источник: Nuances of Programming
Я ежедневно работаю как с Angular, так и с React, а также большой поклонник Vue и Svelte и слежу за их развитием. В этой статье я покажу, как с помощью Angular получить компоненты без рендеринга, как в Vue, и рендер-пропсы, как в React.
Как следует из самого названия, компоненты без рендеринга ничего не рендерят; их единственное назначение — предоставлять функциональность для повторного использования. Давайте возьмем в качестве примера переключатель toggle, написанный на Vue, и преобразуем его на Angular. Вот Vue-версия:
Безрендерный компонент toggle отвечает за API для переключателя представления. Ему все равно, как это представление структурировано или стилизовано. Той же функциональности можно достичь в Angular с помощью структурных директив.
Структурные директивы
Структурная директива изменяет макет DOM, добавляя и удаляя элементы DOM (например, представление view). Дополнением к этому служит такая мощная функция, как предоставление объекта context, который доступен любому адресату структурной директивы.
Создадим структурную директиву toggle, которая предоставляет доступ к API через свойство context:
Мы создаем view и передаем публичный API, который хотим сделать доступным через context, роль которого исполняет второй параметр в createEmbeddedView. Самое интересное здесь то, что TemplateRef принимает универсальный тип, который служит типом для context. Современные IDE, такие как Webstorm, автоматически выводят его в шаблоне. Давайте им воспользуемся:
Спасибо, Webstorm!
ExportAs и его применение
Второй случай разберем на официальном примере рендер-пропсов React. Рендер-пропсы предоставляют возможность одним компонентам совместно использовать состояние или поведение, инкапсулированное в другом компоненте, если им требуется то же самое состояние. Например, следующий компонент React отслеживает положение мыши в веб-приложении:
Мы используем дочерний (children) рендер-проп в качестве функции, которая предоставляет состояние компонента любому потребителю.
Поведение, которым мы хотим поделиться, благодаря этой технике становится максимально портируемым. Чтобы реализовать это поведение, отрисуйте <Mouse> с помощью рендер-пропа, который говорит ей, что нужно визуализировать с текущими координатами курсора (x, y):
Создадим такую же функциональность в Angular:
Компонент MouseComponent не связан с его содержимым. Он предоставляет свой API с помощью свойства exportAs, которое сообщает Angular, что мы можем использовать этот API компонента в шаблоне:
И всё, ничего больше не нужно. Метод exportAs также можно применить вместо структурной директивы для компонента toggle, который мы написали ранее.
Итоги
Не думаю, что есть правильные или неправильные варианты использования, когда речь заходит о структурной директиве или функции exportAs. Преимущества структурных директив заключаются в том, что мы можем явно определить API, который хотим предоставлять в представлении, и проконтролировать, следует ли визуализировать представление или нет. Когда нам все еще нужна какая-то часть представления, как в примере с MouseComponent, можно воспользоваться компонентом и функцией exportAs.
Читайте также:
Перевод статьи Netanel Basal: Going Renderless in Angular: All of the Functionality, None of the Render