Перейти к содержанию

Жизненный цикл компонента

📅 30.09.2026

Этот материал предполагает, что вы уже прочитали руководство по основам. Если Angular для вас в новинку, начните с него.

Жизненный цикл компонента — последовательность шагов от создания до уничтожения. Каждый шаг — отдельная часть того, как Angular отрисовывает компоненты и проверяет их на обновления.

На этих шагах свой код запускают хуки жизненного цикла. Хуки конкретного экземпляра — это методы класса компонента. Хуки всего приложения Angular — функции, которые принимают колбэк.

Жизненный цикл тесно связан с тем, как Angular со временем проверяет компоненты на изменения. Чтобы понять цикл, достаточно знать: Angular обходит дерево приложения сверху вниз и сверяет привязки шаблона. Хуки ниже выполняются во время этого обхода. Каждый компонент посещается ровно один раз, поэтому посреди обхода не стоит менять состояние дальше.

Сводка

Фаза Метод Кратко
Создание constructor Обычный конструктор класса JavaScript . Выполняется, когда Angular создаёт экземпляр компонента.
Обнаружение изменений ngOnInit Выполняется один раз после того, как Angular инициализировал все входные свойства компонента.
ngOnChanges Выполняется каждый раз, когда изменились входные свойства компонента.
ngDoCheck Выполняется каждый раз, когда этот компонент проверяется на изменения.
ngAfterContentInit Выполняется один раз после инициализации содержимого компонента.
ngAfterContentChecked Выполняется каждый раз, когда содержимое этого компонента проверено на изменения.
ngAfterViewInit Выполняется один раз после инициализации представления компонента.
ngAfterViewChecked Выполняется каждый раз, когда представление компонента проверено на изменения.
Отрисовка afterNextRender Выполняется один раз, когда все компоненты в следующий раз отрисованы в DOM.
afterEveryRender Выполняется каждый раз, когда все компоненты отрисованы в DOM.
Уничтожение ngOnDestroy Выполняется один раз перед уничтожением компонента.

ngOnInit

Метод ngOnInit выполняется после того, как Angular записал во все входные свойства компонента начальные значения. У компонента ngOnInit выполняется ровно один раз.

Шаг происходит до инициализации собственного шаблона компонента. Состояние можно обновить по начальным значениям входных свойств.

ngOnChanges

Метод ngOnChanges выполняется после изменения любых входных свойств компонента.

Шаг происходит до проверки собственного шаблона компонента. Состояние можно обновить по начальным значениям входных свойств.

При инициализации первый ngOnChanges выполняется раньше ngOnInit.

Просмотр изменений

Метод ngOnChanges принимает один аргумент SimpleChanges. Это объект-Record: имя каждого входного свойства сопоставлено с объектом SimpleChange. В SimpleChange лежат предыдущее значение, текущее значение и признак того, что входное свойство изменилось впервые.

Для более строгой проверки типов первым аргументом обобщения можно передать текущий класс или this.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@Component({/* ... */})
export class UserProfile {
  name = input('');

  ngOnChanges(changes: SimpleChanges<UserProfile>) {
    if (changes.name) {
      console.log(`Previous: ${changes.name.previousValue}`);
      console.log(`Current: ${changes.name.currentValue}`);
      console.log(`Is first ${changes.name.firstChange}`);
    }
  }
}

Если у входного свойства задан alias, ключом в Record SimpleChanges остаётся имя свойства TypeScript, а не псевдоним.

ngOnDestroy

Метод ngOnDestroy выполняется один раз непосредственно перед уничтожением компонента. Angular уничтожает компонент, когда тот больше не показан на странице: его скрыл @if или произошёл переход на другую страницу.

DestroyRef

Вместо метода ngOnDestroy можно внедрить экземпляр DestroyRef. Колбэк на уничтожение компонента регистрируют методом onDestroy у DestroyRef.

1
2
3
4
5
6
7
8
@Component({/* ... */})
export class UserProfile {
  constructor() {
    inject(DestroyRef).onDestroy(() => {
      console.log('UserProfile destruction');
    });
  }
}

Экземпляр DestroyRef можно передать функциям и классам вне компонента. Так делают, если очистку при уничтожении компонента должен выполнить другой код.

DestroyRef также позволяет держать код настройки рядом с кодом очистки, а не собирать всю очистку в методе ngOnDestroy.

Проверка, уничтожен ли экземпляр

У DestroyRef есть свойство destroyed: по нему видно, уничтожен ли уже данный экземпляр. Это помогает не трогать уничтоженные компоненты, особенно в отложенной и асинхронной логике.

Проверка destroyRef.destroyed не даёт выполнить код после очистки экземпляра и уберегает от ошибок вроде NG0911: View has already been destroyed..

ngDoCheck

Метод ngDoCheck выполняется каждый раз перед тем, как Angular проверит шаблон компонента на изменения.

Этим хуком вручную ищут изменения состояния вне обычного обнаружения изменений Angular и вручную обновляют состояние компонента.

Метод вызывается очень часто и может заметно замедлить страницу. Не объявляйте этот хук, пока нет другого выхода.

При инициализации первый ngDoCheck выполняется после ngOnInit.

ngAfterContentInit

Метод ngAfterContentInit выполняется один раз после инициализации всех потомков, вложенных в компонент (его содержимого).

Этим хуком читают результаты запросов содержимого. Инициализированное состояние запросов доступно, но любая смена состояния в этом методе приводит к ExpressionChangedAfterItHasBeenCheckedError.

ngAfterContentChecked

Метод ngAfterContentChecked выполняется каждый раз, когда потомки, вложенные в компонент (его содержимое), проверены на изменения.

Метод вызывается очень часто и может заметно замедлить страницу. Не объявляйте этот хук, пока нет другого выхода.

Обновлённое состояние запросов содержимого здесь доступно, но любая смена состояния в этом методе приводит к ExpressionChangedAfterItHasBeenCheckedError.

ngAfterViewInit

Метод ngAfterViewInit выполняется один раз после инициализации всех потомков в шаблоне компонента (его представления).

Этим хуком читают результаты запросов представления. Инициализированное состояние запросов доступно, но любая смена состояния в этом методе приводит к ExpressionChangedAfterItHasBeenCheckedError.

ngAfterViewChecked

Метод ngAfterViewChecked выполняется каждый раз, когда потомки в шаблоне компонента (его представление) проверены на изменения.

Метод вызывается очень часто и может заметно замедлить страницу. Не объявляйте этот хук, пока нет другого выхода.

Обновлённое состояние запросов представления здесь доступно, но любая смена состояния в этом методе приводит к ExpressionChangedAfterItHasBeenCheckedError.

afterEveryRender и afterNextRender

Функции afterEveryRender и afterNextRender регистрируют колбэк отрисовки. Он вызывается после того, как Angular закончил отрисовку всех компонентов страницы в DOM.

Эти функции отличаются от остальных хуков в этом руководстве. Это не методы класса, а автономные функции, которые принимают колбэк. Колбэки отрисовки не привязаны к конкретному экземпляру компонента: это хук на всё приложение.

afterEveryRender и afterNextRender нужно вызывать в контексте инъекции, обычно в конструкторе компонента.

Колбэками отрисовки делают ручные операции с DOM. Как работать с DOM в Angular, описано в Использование DOM API.

Колбэки отрисовки не выполняются при серверном рендеринге и при предварительном рендеринге на этапе сборки.

Фазы after*Render

У afterEveryRender и afterNextRender работу можно разбить на фазы. Фаза задаёт порядок операций с DOM: операции записи ставят перед операциями чтения, чтобы не устраивать лишние пересчёты макета. Чтобы передать данные между фазами, функция фазы может вернуть значение, которое прочитает следующая фаза.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import {Component, ElementRef, afterNextRender} from '@angular/core';

@Component(/* ... */)
export class UserProfile {
  private prevPadding = 0;
  private elementHeight = 0;

  constructor() {
    const elementRef = inject(ElementRef);
    const nativeElement = elementRef.nativeElement;

    afterNextRender({
      // Use the `Write` phase to write to a geometric property.
      write: () => {
        const padding = computePadding();
        const changed = padding !== this.prevPadding;
        if (changed) {
          nativeElement.style.padding = padding;
        }
        return changed; // Communicate whether anything changed to the read phase.
      },

      // Use the `Read` phase to read geometric properties after all writes have occurred.
      read: (didWrite) => {
        if (didWrite) {
          this.elementHeight = nativeElement.getBoundingClientRect().height;
        }
      },
    });
  }
}

Фаз четыре, они идут в таком порядке:

Фаза Описание
earlyRead Читайте в этой фазе свойства и стили DOM, которые влияют на раскладку и строго нужны для последующего расчёта. По возможности обходите эту фазу и пользуйтесь фазами write и read.
write Пишите в этой фазе свойства и стили DOM, которые влияют на раскладку.
mixedReadWrite Фаза по умолчанию. Для операций, которым нужно и читать, и писать свойства и стили, влияющие на раскладку. По возможности обходите эту фазу и пользуйтесь явными фазами write и read.
read Читайте в этой фазе свойства DOM, которые влияют на раскладку.

Интерфейсы жизненного цикла

Для каждого метода жизненного цикла в Angular есть интерфейс TypeScript. Интерфейсы можно импортировать и implement, чтобы опечатка в имени метода не прошла незамеченной.

Имя интерфейса совпадает с именем метода без префикса ng. Например, интерфейс для ngOnInit — OnInit.

1
2
3
4
5
6
@Component({/* ... */})
export class UserProfile implements OnInit {
  ngOnInit() {
    /* ... */
  }
}

Порядок выполнения

На схемах ниже — порядок выполнения хуков жизненного цикла Angular.

При инициализации

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
graph TD;
id[constructor]-->CHANGE;
subgraph CHANGE [Change detection]
direction TB
ngOnChanges-->ngOnInit;
ngOnInit-->ngDoCheck;
ngDoCheck-->ngAfterContentInit;
ngDoCheck-->ngAfterViewInit
ngAfterContentInit-->ngAfterContentChecked
ngAfterViewInit-->ngAfterViewChecked
end
CHANGE--Rendering-->afterNextRender-->afterEveryRender

При последующих обновлениях

1
2
3
4
5
6
7
8
graph TD;
subgraph CHANGE [Change detection]
direction TB
ngOnChanges-->ngDoCheck
ngDoCheck-->ngAfterContentChecked;
ngDoCheck-->ngAfterViewChecked
end
CHANGE--Rendering-->afterEveryRender

Порядок вместе с директивами

Если на один элемент с компонентом повешены одна или несколько директив — в шаблоне или через свойство hostDirectives, — фреймворк не гарантирует порядок одного и того же хука между компонентом и директивами на этом элементе. Не опирайтесь на порядок, который удалось наблюдать: в следующих версиях Angular он может измениться.


Источник: https://angular.dev/guide/components/lifecycle

Комментарии