1. Знакомство с директивами в Angular
Директива — это специальная инструкция для Angular, которая говорит ему: “Вот этому элементу или компоненту нужно добавить особое поведение или изменить его внешний вид”.
Если проводить аналогию с HTML, то обычные атрибуты типа disabled, hidden, class — это простые “подсказки” для браузера. А директивы Angular — это такие “супер-атрибуты”, которые могут менять DOM, реагировать на события, управлять структурой страницы и даже внедрять свою бизнес-логику.
Пример:
<button *ngIf="isLoggedIn">Выйти</button>
Выглядит как обычный HTML, но *ngIf — это уже директива! Она решает: показывать этот <button> или не показывать, в зависимости от значения переменной isLoggedIn.
Директивы — это не компоненты
- Компонент — всегда связан с шаблоном (HTML+CSS) и обычно “рисует” кусок интерфейса.
- Директива — не имеет собственного шаблона. Она “вешается” на существующий HTML-элемент и меняет его поведение или внешний вид.
Интересный факт: Любой Angular-компонент — это тоже директива, но с шаблоном! Когда вы пишете @Component, это на самом деле расширяет @Directive.
2. Виды директив в Angular
В Angular есть три основных типа директив. Давайте разберем их по порядку:
| Тип директивы | Пример | Описание |
|---|---|---|
| Атрибутивная | , , |
Меняет поведение или внешний вид существующего элемента. |
| Структурная | , , |
Меняет структуру DOM: добавляет, удаляет или перемещает элементы. |
| Компонент | |
Директива с шаблоном (то есть компонент). |
Атрибутивные директивы
Атрибутивная директива изменяет внешний вид или поведение того элемента, к которому она применена.
Примеры:
- [ngClass] — динамически добавляет или убирает CSS-классы.
- [ngStyle] — динамически меняет стили.
- appHighlight — ваша собственная директива, которая, например, подсвечивает элемент.
Пример использования:
<p [ngClass]="{ 'important': isImportant }">Важное сообщение</p>
Если isImportant === true, класс important добавится к <p>.
Структурные директивы
Структурная директива меняет саму структуру DOM: может добавить, удалить или клонировать элементы.
Признак: Всегда начинается со звёздочки *.
Примеры:
- *ngIf — показывает/скрывает элемент.
- *ngFor — повторяет элемент для каждого значения в массиве.
- *ngSwitch — реализует “переключатель” между разными шаблонами.
Пример:
<ul>
<li *ngFor="let user of users">{{user.name}}</li>
</ul>
Если массив users содержит 5 пользователей, то <li> будет 5 штук!
Компоненты (директивы с шаблоном)
Компонент — это директива, у которой есть собственный шаблон, стили и логика. На практике, когда говорят “директивы”, обычно имеют в виду только атрибутивные и структурные директивы, а компоненты выделяют в отдельную категорию.
3. Как работают директивы? Немного магии Angular
Когда Angular компилирует ваш шаблон, он ищет директивы по селекторам (например, [ngClass], *ngIf или appHighlight). Если находит — “навешивает” соответствующее поведение на элемент.
- Для атрибутивных директив Angular создаёт экземпляр класса-директивы и связывает его с элементом.
- Для структурных Angular может полностью удалить или создать DOM-элемент на лету.
Пример жизненного цикла:
- Angular видит <p appHighlight>Текст</p>.
- Создаёт экземпляр директивы HighlightDirective.
- Передаёт ссылку на элемент, чтобы директива могла его изменить.
- Если в директиве есть подписка на события — она работает, пока элемент жив.
4. Атрибутивные директивы: подробный пример
Давайте создадим свою простую атрибутивную директиву, которая будет подсвечивать элемент при наведении мышки.
Шаг 1. Генерируем директиву
В терминале:
ng generate directive highlight
Angular создаст файл highlight.directive.ts и зарегистрирует директиву.
Шаг 2. Код директивы
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[appHighlight]' // Используем как атрибут!
})
export class HighlightDirective {
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onMouseEnter() {
this.el.nativeElement.style.backgroundColor = 'yellow';
}
@HostListener('mouseleave') onMouseLeave() {
this.el.nativeElement.style.backgroundColor = '';
}
}
Шаг 3. Используем директиву в шаблоне
<p appHighlight>Наведи на меня мышкой — я засвечусь!</p>
Выглядит как магия: никакого лишнего кода в компоненте, просто “украшение” HTML.
5. Структурные директивы: подробный пример
Структурные директивы всегда используют синтаксис с *. Самые популярные — *ngIf и *ngFor.
*ngIf
Показывает или скрывает элемент в зависимости от условия.
<button *ngIf="isLoggedIn">Выйти</button>
Если isLoggedIn === false, кнопки вообще не будет в DOM!
*ngFor
Повторяет элемент для каждого значения в массиве.
<ul>
<li *ngFor="let user of users">{{user.name}}</li>
</ul>
*ngSwitch
Переключает шаблоны по значению.
<div [ngSwitch]="user.role">
<p *ngSwitchCase="'admin'">Администратор</p>
<p *ngSwitchCase="'user'">Пользователь</p>
<p *ngSwitchDefault>Гость</p>
</div>
6. Полезные нюансы
Как создавать свои директивы
Angular позволяет создавать собственные директивы, чтобы переиспользовать логику и не дублировать код.
- Атрибутивная директива
Используется как обычный атрибут: <div appMyDirective></div>
Реализуется как класс с декоратором @Directive. - Структурная директива
Используется со звёздочкой: <div *appMyIf="условие"></div>
Требует внедрения TemplateRef и ViewContainerRef — это чуть сложнее, но возможно!
Краткая таблица: основные директивы Angular
| Директива | Тип | Описание |
|---|---|---|
|
Структурная | Показывает/скрывает элемент по условию |
|
Структурная | Повторяет элемент для каждого значения массива |
|
Структурная | Переключает шаблоны |
|
Атрибутивная | Динамически меняет классы |
|
Атрибутивная | Динамически меняет стили |
|
Атрибутивная | Двусторонняя привязка данных |
Как Angular отличает директиву от обычного атрибута?
- Атрибутивные директивы обычно регистрируются в декораторе @Directive с селектором в квадратных скобках: selector: '[appHighlight]'
- Структурные директивы используют звёздочку * — Angular превращает это в специальный синтаксис под капотом (на самом деле это sugar-синтаксис для <ng-template>).
7. Типичные ошибки при работе с директивами
Ошибка №1: Путают директиву и компонент.
Новички часто думают, что директива — это “маленький компонент”. На самом деле директива не имеет своего шаблона и не рисует ничего в DOM сама по себе. Она только “влияет” на существующий элемент.
Ошибка №2: Забывают добавить директиву в imports.
Если вы создали свою директиву и не добавили её в модуль или в imports массива Standalone-компонента — Angular её не увидит и выдаст ошибку типа “unknown directive”.
Ошибка №3: Используют директиву как тег.
Атрибутивные директивы нельзя использовать как самостоятельные теги (<appHighlight></appHighlight> — ошибка!). Используйте их только как атрибуты: <div appHighlight></div>.
Ошибка №4: Применяют структурную директиву без звёздочки.
Если написать <div ngIf="isVisible"></div>, Angular не поймёт, что вы хотели, и элемент не будет работать как надо. Нужно обязательно использовать *ngIf.
Ошибка №5: Забывают про область действия директивы.
Если директива объявлена только в одном модуле, а вы пытаетесь использовать её в другом — получите ошибку. Не забудьте экспортировать директиву через exports или добавить в нужный модуль.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ