Angular
Директивы: атрибутивные и host
Подсветка элемента при наведении нужна в карточках, кнопках, строках таблицы - в десятках мест. Копировать обработчики mouseenter и стили в каждый компонент означает плодить дублирование. Директива решает это иначе: она инкапсулирует поведение и навешивается на любой элемент одним атрибутом. Написал директиву highlight один раз - и приклеиваешь её куда угодно, не меняя сам элемент. Так Angular добавляет поведение без создания нового компонента.
- Подсветка и тултипы: одна директива добавляет поведение на любой элемент через атрибут
- Автофокус: директива ставит фокус в поле при появлении, переиспользуется во всех формах
- Контроль доступа: директива скрывает или отключает элемент в зависимости от роли пользователя
- Маски ввода и форматирование: директива перехватывает ввод в поле и приводит его к нужному виду
- Angular Material и CDK: огромная часть библиотеки это директивы поведения, а не компоненты
Предварительные знания
- Урок ng-04: привязки свойств и событий
- Урок ng-03: декоратор и selector компонента
- Базовое понимание DOM-событий: click, mouseenter, input
- Идея внедрения зависимостей через inject на уровне знакомства
Атрибутивная директива
Директива похожа на компонент, но без собственного шаблона. Она помечается декоратором @Directive и навешивается на существующий элемент через selector в виде атрибута. Задача директивы - добавить элементу поведение: реагировать на события, менять стиль, перехватывать ввод. Сам элемент остаётся прежним, директива лишь дополняет его.
Селектор [appHighlight] в квадратных скобках означает атрибут: директива срабатывает на любом элементе с этим атрибутом. Через inject(ElementRef) директива получает ссылку на DOM-элемент, к которому прикреплена. Чтобы директива стала доступна в шаблоне, её, как и компонент, добавляют в массив imports.
- Компонент — Имеет свой шаблон и создаёт собственную разметку. Это новый кусок интерфейса
- Атрибутивная директива — Шаблона нет. Добавляет поведение существующему элементу, не создавая разметки
Прямое обращение к nativeElement через стиль показано для простоты. На практике для манипуляций предпочтительнее host-привязки, разбираемые дальше: они декларативны и работают корректно при SSR, где DOM может отсутствовать.
Чем атрибутивная директива принципиально отличается от компонента?
Привязки и слушатели через host
Элемент, на котором висит директива, называют host (носитель). Объект host в декораторе декларативно описывает, что директива делает с этим элементом: какие свойства и атрибуты привязать и какие события слушать. Ключи в квадратных скобках - привязки свойств, в круглых - слушатели событий. Это тот же синтаксис, что и в шаблонах.
Здесь привязка [style.background] меняет фон в зависимости от сигнала active, а слушатели mouseenter и mouseleave переключают этот сигнал. Поведение полностью декларативно: никакого ручного addEventListener и обращения к nativeElement. Директива переиспользуется на любом элементе одним атрибутом appHighlight.
В объекте host строковые значения без скобок задают статические атрибуты, например 'class': 'card'. Квадратные скобки делают привязку динамической, а круглые - слушателем события. Эта симметрия совпадает с привязками в шаблоне, поэтому отдельный синтаксис учить не нужно.
Что описывает объект host в декораторе директивы?
Композиция через hostDirectives
Иногда компоненту или директиве нужно вобрать поведение нескольких готовых директив, не повторяя их код. Для этого служит hostDirectives: в декораторе перечисляются другие директивы, и их поведение автоматически применяется к носителю. Это композиция вместо наследования - предпочтительный способ переиспользования в Angular.
Теперь FancyButton автоматически получает подсветку из Highlight и поведение тултипа из Tooltip без копирования их кода. Можно даже пробросить входы и выходы вобранных директив наружу, чтобы родитель управлял ими через FancyButton. Так из мелких поведенческих кирпичиков собираются богатые компоненты.
Особняком стоят структурные директивы - те, что меняли структуру DOM через звёздочку, как *ngIf и *ngFor. В современном Angular их ниша почти полностью закрыта встроенным control flow: @if, @for и @switch делают то же самое, но быстрее и без импортов. Писать собственные структурные директивы теперь нужно крайне редко.
| Тип | Что делает | Статус в 2026 |
|---|---|---|
| Атрибутивная | Поведение на существующем элементе | Активно используется |
| Структурная (*) | Меняла структуру DOM | Заменена встроенным control flow |
| hostDirectives | Композиция поведения | Современный способ переиспользования |
Что позволяет hostDirectives и что произошло со структурными директивами?
Связь с другими темами
Директивы дополняют элементы и компоненты поведением:
- Шаблоны и привязки — Директивы используют тот же синтаксис привязок свойств и событий
- Встроенный control flow — Структурные директивы прошлого заменены на @if и @for
- Связь компонентов — Директивы навешиваются на проецируемые элементы, расширяя их поведение
Итог
- Атрибутивная директива - класс с декоратором @Directive, добавляющий поведение элементу без своего шаблона
- Объект host в декораторе задаёт привязки свойств, атрибутов и слушатели событий на самом элементе-носителе
- Через inject директива получает ссылку на свой элемент и реагирует на события вроде наведения или клика
- hostDirectives позволяет компоненту или директиве вобрать поведение других директив - это композиция
- Структурные директивы со звёздочкой больше почти не нужны: их нишу закрыл встроенный control flow @if и @for
Связанные уроки
- ng-04-templates-binding — Директивы используют те же привязки свойств и событий, что разобраны в шаблонах
- ng-05-control-flow — Структурные директивы *ngIf и *ngFor заменены встроенным control flow