Шесть основных директив Angular: ngIf, ngFor, ngClass, ngStyle, ngModel, ngSwitch

Этот материал объясняет, что такое директивы в Angular и как использовать шесть наиболее распространённых: ngIf, ngFor, ngClass, ngStyle, ngModel и ngSwitch. Включены готовые примеры кода, советы по производительности, распространённые ошибки и чек-листы для разработчика и ревьюера.
О чём эта статья
Angular позволяет встраивать логику в HTML с помощью директив. Одни директивы меняют структуру DOM (показывают/скрывают, повторяют блоки), другие — атрибуты и стили. Ниже — краткая таблица с быстрым обзором, после неё — детальные примеры и дополнительные рекомендации.
| Директива | Тип | Описание |
|---|---|---|
| *ngIf | Структурная | Показывает или скрывает блок в зависимости от условия. |
| *ngFor | Структурная | Повторяет блок для каждого элемента коллекции. |
| [ngClass] | Атрибутная | Применяет CSS-класс(ы) условно. |
| [ngStyle] | Атрибутная | Применяет inline-стили условно. |
| [(ngModel)] | Атрибутная | Двусторонняя привязка значения между шаблоном и компонентом. |
| [ngSwitch] | Структурная | Реализует switch/case в шаблоне для разных вариантов отображения. |
Важно: структурные директивы (ngIf, ngFor, ngSwitch) управляют структурой DOM. Атрибутные директивы (ngStyle, ngClass, ngModel) меняют свойства существующих элементов.
Что такое директивы Angular?
Директивы — это механизмы, которые расширяют HTML. Они позволяют вставлять условную логику (if), циклы (for), связывать данные и управлять классами и стилями прямо в шаблоне. В одной строке: директива — это инструкция Angular, которая изменяет поведение DOM-элемента.
Важно: директивы не заменяют TypeScript-логику. Их задача — выразительно и декларативно описывать связь между состоянием приложения и тем, что видит пользователь.
Как использовать ngIf
ngIf показывает элемент только если условие истинно.
Пример: пусть в компоненте есть логика, которая помечает отсутствие плейлистов.
TypeScript (component.ts):
noPlaylists: boolean = false;
playlists: any = [];
constructor() { }
ngOnInit(): void {
if (this.playlists.length === 0) {
this.noPlaylists = true;
}
}HTML (template):
Плейлистов не найдено.
Добавление альтернативного шаблона (else):
Плейлистов не найдено.
Плейлисты найдены.
Примечание: ngIf полностью удаляет элемент из DOM, когда условие ложно. Если вам нужно лишь спрятать элемент визуально, используйте CSS (display: none) или привязку к классу.
Когда применять ngIf
- Показывать ошибки, сообщения «нет данных», модальные окна и т. п.
- Не использовать для частых переключений, если важны сохранённые состояния дочерних компонентов — ngIf уничтожит их при скрытии.
Как использовать ngFor
ngFor воспроизводит фрагмент шаблона для каждого элемента коллекции.
TypeScript (component.ts):
playlists: any = [
{ "name": "Rock", "numberOfSongs": 5 },
{ "name": "Contemporary", "numberOfSongs": 9 },
{ "name": "Popular", "numberOfSongs": 14 },
{ "name": "Acoustic", "numberOfSongs": 3 },
{ "name": "Wedding Songs", "numberOfSongs": 25 },
{ "name": "Metal", "numberOfSongs": 0 }
];HTML (template):
Плейлисты найдены.
{{playlist.name}}
{{playlist.numberOfSongs}} песен
Подсказки по производительности:
- При рендеринге длинных списков указывайте trackBy, чтобы Angular не перемонтировал все элементы при каждом изменении.
Пример с trackBy:
trackById(index: number, item: any) {
return item.id ?? index;
}Как использовать ngClass
ngClass удобно использовать для условного назначения классов.
CSS:
.songs { background-color: #F7F5F2; }
.noSongs { background-color: #FFA8A8; }HTML (template):
0 ? 'songs' : 'noSongs'">
{{playlist.name}}
{{playlist.numberOfSongs}} песен
Если плейлист содержит песни — применяется класс songs (серый фон), иначе — noSongs (красный фон).
Альтернативы и вариации:
- Можно комбинировать строки и массивы классов.
Как использовать ngStyle
ngStyle задаёт inline-стили на основе выражений.
HTML:
0 ? '#F7F5F2' : '#FFA8A8' }">
{{playlist.name}}
{{playlist.numberOfSongs}} песен
Несколько стилей через запятую:
[ngStyle]="{
'background-color': playlist.numberOfSongs > 0 ? '#F7F5F2' : '#FFA8A8',
'color': playlist.numberOfSongs > 0 ? 'black' : 'darkblue'
}"Примечание: inline-стили сложнее переопределять и поддерживать, чем классы. Используйте ngStyle для динамических вычисляемых значений (напр., высота на основе данных), а ngClass — для семантических смен состояний.
Как использовать ngModel
ngModel обеспечивает двустороннюю привязку значения между шаблоном и компонентом. Для этого нужно импортировать FormsModule.
app.module.ts:
import { FormsModule } from '@angular/forms';
@NgModule({
imports: [
...,
FormsModule
]
})
export class AppModule {}Компонент:
renamingPlaylists: boolean = false;
public playlists: any = [ /* ... */ ];Шаблон — кнопки для включения режима переименования:
Поле ввода с двусторонней привязкой:
В результате при вводе нового имени значение playlist.name обновляется в компоненте и во всех местах шаблона, где оно используется.
Советы по валидации:
- Для более сложной валидации рассмотрите Reactive Forms (FormControl, FormGroup) вместо ngModel.
- При работе с динамическими формами учитывайте отписку от подписок и управление состоянием.
Как использовать ngSwitch
ngSwitch работает как switch/case в шаблоне.
Добавим рейтинг для плейлистов (0–5):
public playlists: any = [
{ "name": "Rock", "numberOfSongs": 5, "rating": 5 },
{ "name": "Contemporary", "numberOfSongs": 9, "rating": 1 },
{ "name": "Popular", "numberOfSongs": 14, "rating": 5 },
{ "name": "Acoustic", "numberOfSongs": 3, "rating": 4 },
{ "name": "Wedding Songs", "numberOfSongs": 25, "rating": 5 },
{ "name": "Metal", "numberOfSongs": 0, "rating": 0 }
];Шаблон для отображения звёздочек:
{{playlist.name}}
{{playlist.numberOfSongs}} песен
★
★★
★★★
★★★★
★★★★★
Нет оценок
Общие ошибки и когда директивы подводят
- Использование ngIf для очень частых переключений на элементах, у которых есть внутреннее состояние — состояние будет теряться.
- Отсутствие trackBy в ngFor при больших массивах — приводит к лишним перестроениям DOM.
- Смешивание ngClass и ngStyle там, где следует использовать только классы для семантики и поддержки темизации.
- Использование ngModel в крупных формах без контроля валидации — лучше Reactive Forms.
Чек-листы
Чек-лист разработчика перед PR:
- Есть ли trackBy для ngFor в длинных списках?
- Не удаляет ли ngIf важные состояния компонента (повторно создаёт контролы)?
- Используются ли классы вместо inline-стилей там, где уместно?
- Подключён ли FormsModule, если используется ngModel?
- Есть ли тесты для критичных шаблонных сценариев?
Чек-лист ревьюера:
- Понимает ли автор, почему выбрана структурная директива, а не CSS?
- Налицо ли потенциальная проблема с производительностью (частые изменения, длинные списки)?
- Правильно ли обработаны пустые состояния и ошибки?
Ментальные модели (как думать о директивах)
- ngIf = включатель/выключатель DOM: элемент существует или нет.
- ngFor = генератор элементов по данным.
- ngClass/ngStyle = внешний вид по состоянию.
- ngModel = двунаправленная связь для простых форм.
- ngSwitch = выбор между несколькими готовыми вариантами отображения.
Быстрая шпаргалка (cheat sheet)
- ngIf — структурная, удаляет из DOM. Используйте для пустых состояний.
- ngFor — структурная, используйте trackBy для оптимизации.
- [ngClass] — применяйте классы по условию.
- [ngStyle] — применяйте динамические inline-стили.
- [(ngModel)] — двусторонняя привязка, не забудьте FormsModule.
- [ngSwitch] — для множественных вариантов представления.
Mermaid-диаграмма выбора директивы:
flowchart TD
A[Нужно ли полностью убрать элемент из DOM?] -->|Да| B[ngIf]
A -->|Нет| C[Нужно только скрыть визуально?]
C -->|Да| D[CSS / класс с display:none]
C -->|Нет| E[Нужно повторять блок для коллекции?]
E -->|Да| F[ngFor]
E -->|Нет| G[Нужно изменить стиль?]
G -->|Классы| H[ngClass]
G -->|Inline| I[ngStyle]
F --> J[trackBy?]
J -->|Да| K[Добавить trackBy]Короткий глоссарий
- Директива — инструкция Angular, изменяющая DOM или свойства элементов.
- Структурная директива — влияет на структуру DOM (например, ngIf, ngFor).
- Атрибутная директива — меняет поведение или внешний вид существующего элемента.
Советы по безопасности и доступности
- Всегда валидируйте пользовательский ввод на стороне сервера, даже если используете ngModel и валидацию в клиенте.
- Обеспечьте доступность: у скрытых блоков используйте aria-атрибуты, если блок временно скрывается, но важен для скринридеров.
Миграция и совместимость
- Большинство директив описанных здесь применимы в Angular (v2+). При обновлении версии Angular следите за изменениями API форм и за тем, как фреймворк обрабатывает рендеринг.
Когда использовать альтернативы
- Для сложных форм и проверок используйте Reactive Forms вместо ngModel.
- Для очень больших списков (несколько тысяч элементов) рассмотрите виртуализацию (cdk-virtual-scroll-viewport).
Важно: элементы управления состоянием, сторонние библиотеки и производительность часто диктуют архитектурные решения. Директивы — инструмент, а не замена архитектуры.
Итог
Вы узнали, как работают шесть распространённых директив Angular: ngIf, ngFor, ngClass, ngStyle, ngModel и ngSwitch. Примеры показаны как в TypeScript, так и в шаблонах. Используйте trackBy для больших списков, Reactive Forms для сложной валидации и следите за потерей состояния при частом использовании ngIf.
Ключевые рекомендации:
- Выбирайте директиву по задаче: структурную для структуры, атрибутную для внешнего вида.
- Старайтесь держать шаблоны простыми и переносить логику в компонент.
- Тестируйте крайние случаи: пустые состояния, асинхронные данные, ошибки сети.
Спасибо за чтение. Применяйте эти приёмы в своём коде и адаптируйте паттерны под архитектуру приложения.
Похожие материалы
Как загрузить субтитры в Kodi
Как пользоваться приложением «Фото» в Windows 11
Установка Proxmox VE на Linux‑сервер
Вернуть адресную строку Safari наверх на iPhone
Ghost CMS локально: установка на Mac и Windows