Angular
Пайпы и async pipe
Дата с сервера приходит как 2026-06-07T10:30:00Z, а на экране пользователь должен видеть 7 июня 2026. Цена хранится числом 1990, а показывается как 1 990 рублей. Писать форматирование в классе компонента для каждого поля - значит засорять логику кодом отображения. Пайп решает это в шаблоне: значение проходит через вертикальную черту и преобразуется на лету. Логика остаётся чистой, а форматирование живёт там, где ему место - в разметке.
- Даты и время: пайп date приводит ISO-строку сервера к локальному человекочитаемому виду
- Цены и валюты: пайп currency форматирует число с символом валюты и разделителями разрядов
- Потоки данных: async pipe подписывается на observable и сам отписывается при уничтожении компонента
- Отладка: пайп json показывает структуру объекта прямо в шаблоне при разработке
- Локализация: один пайп date или currency подстраивается под локаль пользователя без правки логики
Предварительные знания
- Урок ng-04: интерполяция и привязки
- Урок ng-05: проверка данных через @if
- Базовое понимание observable из RxJS на уровне идеи потока
- Идея форматирования: преобразование значения для показа
Встроенные пайпы
Пайп - это преобразователь значения в шаблоне. Значение ставится слева от вертикальной черты, имя пайпа справа: значение | имяПайпа. Пайп берёт исходное значение и возвращает форматированное, не меняя само поле компонента. Angular поставляет набор встроенных пайпов для самых частых задач форматирования.
Пайпы принимают параметры через двоеточие. date:'longDate' задаёт формат даты, currency:'RUB' - код валюты. Параметров может быть несколько подряд. Пайп json удобен при отладке: он печатает объект как форматированный JSON прямо на странице. Пайп keyvalue превращает объект в массив пар ключ-значение для перебора в @for.
| Пайп | Что делает | Пример |
|---|---|---|
| date | Форматирует дату | createdAt | date:'short' |
| currency | Денежный формат с валютой | price | currency:'USD' |
| json | Печатает объект как JSON | obj | json |
| keyvalue | Объект в пары ключ-значение | map | keyvalue |
| uppercase | Верхний регистр строки | name | uppercase |
Пайпы можно соединять цепочкой: значение | пайп1 | пайп2. Результат первого пайпа становится входом второго. Например, date | date:'fullDate' | uppercase сначала отформатирует дату, затем переведёт её в верхний регистр.
Что делает пайп в выражении {{ price | currency:'RUB' }}?
Async pipe для потоков
Многие данные приходят асинхронно через observable из RxJS - например, ответ HTTP-запроса. Чтобы показать их в шаблоне, нужно подписаться на поток, взять значение и не забыть отписаться при уничтожении компонента. Async pipe делает всё это сам: он подписывается, отдаёт последнее пришедшее значение и автоматически отписывается, когда компонент уничтожается.
Связка async pipe с @if и as - частый приём: пока поток не выдал значение, результат null и рисуется ветка @else со спиннером. Как только данные пришли, они попадают в переменную users и отображаются. Ручная подписка и отписка не нужны, что убирает классическую утечку памяти от забытого unsubscribe.
В современном Angular многие потоки удобнее превращать в сигналы через toSignal или сразу использовать httpResource. Но async pipe остаётся самым прямым способом показать observable в шаблоне, особенно при работе с существующим RxJS-кодом.
Какую рутинную работу берёт на себя async pipe?
Свой пайп: чистый и нечистый
Когда встроенных пайпов не хватает, пишут свой. Это класс с декоратором @Pipe и методом transform: на вход приходит значение и параметры, на выходе - преобразованный результат. Как и компонент, свой пайп добавляют в массив imports, чтобы он стал доступен в шаблоне.
По умолчанию пайп чистый: Angular вызывает transform заново только при изменении входного значения. Это эффективно - результат кэшируется, пока вход не поменялся. Нечистый пайп (pure: false) пересчитывается при каждой проверке изменений, даже если вход тот же. Это дорого и нужно лишь в редких случаях, например когда пайп зависит от внутреннего изменяемого состояния.
- Чистый пайп (по умолчанию) — transform вызывается только при изменении входа. Результат кэшируется, поведение быстрое и предсказуемое
- Нечистый пайп (pure: false) — transform вызывается при каждой проверке изменений. Дорого по производительности, применять осознанно и редко
Нечистый пайп выполняется очень часто, поэтому тяжёлые вычисления в нём бьют по производительности всего приложения. Если данные зависят от изменяемой коллекции, обычно лучше пересчитать значение в computed или вернуть новую ссылку, а пайп оставить чистым.
Чем чистый пайп отличается от нечистого по поведению?
Связь с другими темами
Пайпы преобразуют значения на пути из логики в разметку:
- Шаблоны и привязки — Пайпы применяются прямо внутри интерполяции и привязок
- Встроенный control flow — @if часто проверяет результат async pipe перед показом данных
- Директивы — Пайпы и директивы вместе расширяют возможности шаблона без логики в компоненте
Итог
- Пайп преобразует значение прямо в шаблоне через синтаксис значение | имяПайпа, не засоряя логику компонента
- Встроенные пайпы покрывают частые задачи: date, currency, json, keyvalue и другие
- Async pipe подписывается на observable, отдаёт последнее значение и автоматически отписывается при уничтожении компонента
- Чистый пайп пересчитывается только при изменении входа, нечистый - при каждой проверке, что дороже
- Свой пайп - это класс с декоратором @Pipe и методом transform, добавляемый в imports компонента
Связанные уроки
- ng-04-templates-binding — Пайпы применяются внутри интерполяции и привязок, разобранных в шаблонах
- ng-05-control-flow — @if часто проверяет результат async pipe перед отрисовкой загруженных данных