Как обнаружить изменения в Angular: пошаговая инструкция
- 24 мая 2025
Как разработчики на Angular, мы нередко задумываемся, как фреймворк отслеживает изменения в данных и затем отображает их во вьюхе. Этот процесс называется стратегией обнаружения изменений в Angular. В этом материале мы разберёмся, как это работает, и научимся выбирать подходящую стратегию для разных сценариев.
Что такое обнаружение изменений?
Основной принцип обнаружения изменений — это сравнение двух состояний: текущего и нового. Если между ними есть различия, это означает, что произошло изменение, и представление необходимо обновить.

Обнаружение изменений в Angular
В целом, процесс обнаружения изменений в Angular состоит из двух этапов: — Разработчик обновляет модель данных — Angular повторно рендерит обновлённую модель данных во вьюху
Во время цикла обнаружения изменений Angular проходит по всем привязкам, повторно выполняет все выражения, сравнивает их с предыдущими значениями и, если обнаружено изменение, передаёт его в элементы DOM.
Посмотрим на следующую схему:

Приложение на Angular по своей структуре представляет собой так называемое дерево компонентов. На приведённой выше схеме видно, что ForgotPasswordComponent
является дочерним по отношению к LoginComponent
. Это значит, что когда разработчик вносит изменения в модель данных внутри ForgotPasswordComponent
, срабатывает механизм обнаружения изменений.

На изображении выше видно, что после того как механизм обнаружения изменений запускается в ForgotPasswordComponent
, он проходит через все компоненты в дереве компонентов. Поток выполнения выглядит следующим образом:
— Каждый компонент в дереве проверяется на предмет изменений в модели, от которой он зависит. Обнаружение изменений начинается сверху вниз.
— Если Angular обнаруживает, что в другой модели также произошли изменения, он обновляет соответствующий компонент и повторно рендерит его представление.
То, как Angular запускает обнаружение изменений — начиная с корня и последовательно спускаясь вниз по дереву, — делает систему более предсказуемой и производительной. Это становится возможным благодаря реализованному в Angular однонаправленному потоку данных. Это означает, что представление не может быть обновлено после его первоначального формирования. Чтобы отобразить обновлённые изменения, Angular должен заново пройти весь цикл обнаружения изменений.
Жёсткое соблюдение однонаправленного потока данных помогает также эффективнее находить и устранять ошибки, связанные с несогласованными состояниями. В рамках этой статьи мы не будем подробно разбирать однонаправленный поток данных и перейдём непосредственно к стратегиям обнаружения изменений в Angular.
Стратегии обнаружения изменений в Angular
Фреймворк Angular предлагает две стратегии для выполнения обнаружения изменений:
Default
OnPush
Стратегия Default (по умолчанию)
Если явно не указать, какую стратегию использовать, Angular применит стратегию ChangeDetectionStrategy.Default
. При такой стратегии Angular не делает предположений о зависимостях компонента и проверяет каждый компонент в дереве — от корня до листьев — при каждом событии, которое запускает механизм обнаружения изменений. К таким событиям относятся:
— действия пользователя в браузере (например, клики, ввод текста),
— таймеры (setTimeout
, setInterval
),
— сетевые запросы (XHR
),
— асинхронные операции (Promises
и др.).
Такой подход может негативно сказаться на производительности, особенно в больших приложениях с большим количеством компонентов, поскольку Angular выполняет полную проверку дерева компонентов при любом изменении.
Стратегия обнаружения изменений OnPush
Мы можем изменить стратегию обнаружения изменений с default
на ChangeDetectionStrategy.OnPush
, добавив свойство changeDetection
в декоратор @Component
.
@Component({
selector: 'user-view',
changeDetection: ChangeDetectionStrategy.OnPush,
template: ...
})
export class UserView {
...
}
При использовании стратегии OnPush
Angular пропускает проверку компонентов, у которых установлена эта стратегия, а также всех их дочерних компонентов.

При этой стратегии Angular обновляет компонент только если выполняется одно или несколько из следующих условий:
— Изменилась ссылка на входной параметр
— Произошло событие в самом компоненте или в одном из его дочерних компонентов
— AsyncPipe
, связанный с шаблоном, эмитирует новое значение
— Обнаружение изменений было запущено вручную
Далее мы рассмотрим эти случаи подробнее.
Ссылка на входной параметр (Input Reference)
По умолчанию Angular запускает механизм обнаружения изменений каждый раз, когда данные, передаваемые через @Input()
, изменяются или модифицируются. Однако при использовании стратегии OnPush обнаружение изменений срабатывает только если в @Input()
передана новая ссылка на объект.
Именно поэтому предпочтительнее использовать иммутабельные объекты — такие объекты можно изменить только путём создания новой ссылки. Комбинируя иммутабельность и стратегию OnPush
, мы получаем гарантию, что Angular отреагирует на каждое изменение, поскольку ссылка будет отличаться от предыдущей.
Срабатывание обработчика событий
При использовании стратегии OnPush
, каждый раз когда сам компонент или один из его дочерних компонентов вызывает обработчик события, Angular запускает цикл обнаружения изменений для всех компонентов в дереве.
Однако следует помнить: некоторые действия не запускают механизм обнаружения изменений при стратегии OnPush. К ним относятся:
— setTimeout
— setInterval
— Promises
— любые подписки на RxJS Observable (.subscribe()
)
В этих случаях обновление интерфейса не произойдёт автоматически — его нужно инициировать вручную.
AsyncPipe
Встроенный в Angular AsyncPipe
внутренне вызывает markForCheck
каждый раз, когда эмитируется новое значение. Позже мы рассмотрим, как вручную запускать обнаружение изменений. Исходный код можно посмотреть здесь. Благодаря тому, как реализован AsyncPipe
, он работает автоматически со стратегией обнаружения изменений OnPush
.
private _updateLatestValue(async: any, value: Object): void {
if (async === this._obj) {
this._latestValue = value;
this._ref.markForCheck();
}
}
Именно благодаря такой реализации AsyncPipe
работает автоматически и корректно взаимодействует со стратегией обнаружения изменений OnPush
— вам не нужно делать ничего вручную, чтобы обновить представление при приходе новых данных из потока.
Реализация встроенного AsyncPipe в Angular
Возникает логичный вопрос: как запустить обнаружение изменений без использования AsyncPipe
? Это можно сделать вручную с помощью следующих методов — рассмотрим их далее.
Ручной запуск обнаружения изменений
Мы можем вручную запустить механизм обнаружения изменений, используя методы detectChanges()
, ApplicationRef.tick()
и markForCheck()
, который уже упоминался в контексте AsyncPipe
.
— detectChanges()
из ChangeDetectorRef
— запускает обнаружение изменений для текущего представления и всех его потомков.
— ApplicationRef.tick()
— запускает обнаружение изменений во всех компонентах дерева (по сути, во всём приложении).
— markForCheck()
из ChangeDetectorRef
— помечает всех родительских компонентов со стратегией OnPush
для проверки в текущем или следующем цикле обнаружения изменений. Этот метод не запускает обнаружение изменений напрямую, а лишь указывает Angular, что соответствующие компоненты нужно проверить.
Итоги
Механизм обнаружения изменений в Angular достаточно гибкий и предоставляет нам два варианта на выбор — стратегию по умолчанию или стратегию OnPush
.
Используя OnPush
, вы получаете больший прирост производительности, поскольку Angular не проверяет каждый компонент при каждом цикле обнаружения изменений, как это делает стратегия Default. Вместо этого вы явно управляете обновлениями через ссылки на входные параметры.
Кроме того, OnPush
стимулирует использование иммутабельных данных, так как обновления происходят только при изменении ссылки на объект, что делает логику приложения более предсказуемой и надёжной.
«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.
Читать дальше

AOT против JIT-компилятора: что лучше для разработки на Angular?
Angular — один из самых популярных фреймворков для фронтенда — предлагает два подхода к компиляции: предварительная компиляция и динамическая компиляция во время выполнения. Оба метода играют важную роль в оптимизации приложений на Angular и повышении их производительности. В этом материале мы рассмотрим различия между ними, их преимущества и разберёмся, когда стоит использовать каждый из подходов.
- 25 мая 2025

Динамические формы в Angular 19: пошаговое руководство
Формы — неотъемлемая часть большинства веб-приложений: будь то регистрация, ввод данных или опросы. Модуль реактивных форм в Angular отлично подходит для создания статичных форм, но во многих случаях требуется, чтобы форма могла динамически адаптироваться в зависимости от действий пользователя или внешних данных.
В этой статье мы рассмотрим, как создавать динамические формы с использованием автономных компонентов в Angular 19, применяя модульный подход, который избавляет от необходимости использовать традиционные модули Angular. В сопроводительном репозитории на GitHub для оформления форм используется Tailwind CSS, однако в статье внимание сосредоточено исключительно на логике динамических форм. Tailwind и связанные с ним настройки намеренно не включены в примеры, чтобы сохранить акцент на основной теме.
- 25 мая 2025

Компоненты в Angular 18: пошаговое руководство
Angular развивается стремительно, и с выходом версии 18 появились новые возможности, которые разработчики могут использовать в своей работе. Одним из ключевых изменений в Angular 18 стало удаление традиционного файла app.module.ts — ему на смену пришли standalone-компоненты. Если вы только начинаете работать с Angular или переходите с более ранней версии, это пошаговое руководство поможет вам разобраться в базовых принципах компонентов в Angular 18. Независимо от вашего уровня — новичок вы или опытный разработчик — этот туториал покажет, как создавать, управлять и эффективно использовать компоненты в Angular.
- 19 мая 2025

Полное руководство по Angular @if
Одно из самых заметных нововведений в Angular — это встроенный синтаксис для управляющих конструкций, который появился в версии 17. Он решает одну из самых частых задач, с которой сталкивается каждый разработчик: показывать или скрывать элементы на странице в зависимости от условия. Раньше для этого использовали привычную структурную директиву *ngIf
. Теперь у нас есть более современная альтернатива — синтаксис @if
, часть нового подхода к управлению шаблоном.
В этом гайде мы сравним оба варианта, разберёмся, чем @if
лучше, и покажем, как можно перейти на него автоматически. Также поговорим об одной распространённой ошибке — о том, как не стоит использовать @if
вместе с пайпом async
.
- 18 мая 2025

Модули Angular для организации кода и ленивой загрузки
Модули — один из ключевых инструментов Angular для построения масштабируемых и поддерживаемых приложений. В этой статье мы подробно рассмотрим:
- что такое модули в Angular;
- зачем они нужны;
- как их использовать для структурирования кода;
- как реализовать «ленивую» загрузку модулей;
- и чем отличаются Feature, Core и Shared модули.
Если вы только начинаете изучать Angular или хотите углубить свои знания, эта статья поможет вам лучше понять, как правильно организовать архитектуру Angular-приложения.
- 12 мая 2025

Навигация в Angular: RouterLink, Router.navigate и Router.navigateByUrl
Директива RouterLink
позволяет настраивать переходы между маршрутами прямо в шаблоне Angular. А методы Router.navigate
и Router.navigateByUrl
, доступные в классе Router
, дают возможность управлять навигацией программно — прямо из кода компонентов.
Разберёмся, как работают RouterLink
, Router.navigate
и Router.navigateByUrl
.
- 11 мая 2025

Полное руководство по Lazy Loading в Angular
Если вы создаёте большое Angular-приложение, вам наверняка важно, чтобы оно загружалось быстро. Представьте, что вы устраиваете вечеринку и хотите подавать закуски не сразу, а по мере прихода гостей, чтобы не перегрузить кухню. «Ленивая» загрузка в Angular работает примерно так же: вместо того чтобы загружать всё приложение целиком сразу, вы подгружаете только те части, которые нужны — и только когда они нужны.
В этом пошаговом руководстве мы разберём, как реализовать lazy loading в Angular.
- 10 мая 2025

Все (ну или почти все) способы автоматически перезагрузить страницу раз в N секунд
Иногда страницу нужно просто перезагрузить. Полностью. Не компонент, не блок, а именно целиком. Без обсуждений, без лишней логики. Например, чтобы:
- экран с результатами обновлялся каждые 10 секунд;
- интерфейс на стенде показывал последние данные без кнопок;
- страницы в интранете не устаревали, пока никто не смотрит.
Это можно сделать в любой связке: HTML, JS, Python, PHP, Go, Node.js — не важно. Ну и если говорить совсем прямо, то совсем разных способов всего три, а остальное просто вариации.
- 5 мая 2025

Поиск с конца массива в JavaScript: findLast и findLastIndex в JavaScript
С недавних пор в JavaScript появились два полезных метода для массивов: findLast
и findLastIndex
. Они делают то же, что и привычные find
и findIndex
, только проходят массив с конца.
- 5 мая 2025

Vite 6: Новый этап в развитии фронтенд-разработки
Vite — это современный инструмент сборки, который значительно ускоряет процесс разработки фронтенда, благодаря своим невероятно быстрым и удобным функциям. И вот, наконец, вышел новый релиз Vite 6, который приносит массу улучшений и новых возможностей для разработчиков. Давайте посмотрим, что нового появилось в Vite 6 и как это может повлиять на вашу работу.
- 16 января 2025