Жизненный цикл компонентов
СОВЕТ: Предполагается, что вы уже прочитали руководство по основам. Если вы только начинаете работать с Angular, сначала прочитайте его.
Жизненный цикл компонента — это последовательность шагов, которые происходят между созданием и уничтожением компонента. Каждый шаг представляет собой отдельную часть процесса Angular по отображению компонентов и проверке изменений в них с течением времени.
В компонентах можно реализовать хуки жизненного цикла, чтобы выполнять код на этих этапах. Хуки жизненного цикла, связанные с конкретным экземпляром компонента, реализуются как методы класса компонента. Хуки жизненного цикла, относящиеся ко всему приложению Angular, реализуются как функции, принимающие callback.
Жизненный цикл компонента тесно связан с тем, как Angular проверяет изменения в компонентах с течением времени. Чтобы понять этот жизненный цикл, достаточно знать, что Angular обходит дерево приложения сверху вниз, проверяя изменения привязок шаблона. Описанные ниже хуки жизненного цикла выполняются во время этого обхода. При обходе каждый компонент посещается ровно один раз, поэтому всегда следует избегать изменения состояния в середине этого процесса.
Краткое описание
| Этап | Метод | Описание |
| Создание | constructor | Стандартный конструктор класса JavaScript . Выполняется при создании экземпляра компонента Angular. |
| Обнаружение изменений |
ngOnInit | Выполняется один раз после инициализации всех входных параметров компонента. |
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 в качестве первого аргумента обобщённого типа.
@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, запись SimpleChanges всё равно использует в качестве ключа имя свойства TypeScript, а не псевдоним.
ngOnDestroy
Метод ngOnDestroy выполняется один раз непосредственно перед уничтожением компонента. Angular уничтожает компонент, когда он больше не отображается на странице, например, если он скрыт с помощью @if или при переходе на другую страницу.
DestroyRef
Вместо метода ngOnDestroy можно внедрить экземпляр DestroyRef. Чтобы зарегистрировать callback, который будет вызван при уничтожении компонента, вызовите метод onDestroy объекта DestroyRef.
@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 позволяют зарегистрировать callback рендеринга, который будет вызван после того, как Angular завершит отображение в DOM всех компонентов страницы.
Эти функции отличаются от других хуков жизненного цикла, описанных в этом руководстве. Это не методы класса, а отдельные функции, принимающие callback. Выполнение callback рендеринга не привязано к какому-либо конкретному экземпляру компонента: это хук уровня всего приложения.
Функции afterEveryRender и afterNextRender необходимо вызывать в контексте внедрения зависимостей, обычно в конструкторе компонента.
Callback рендеринга можно использовать для выполнения операций с DOM вручную. Рекомендации по работе с DOM в Angular см. в разделе Использование API DOM.
Callback рендеринга не выполняются при рендеринге на стороне сервера или предварительном рендеринге во время сборки.
Этапы after*Render
При использовании afterEveryRender или afterNextRender работу можно разделить на этапы. Этап позволяет управлять последовательностью операций с DOM, задавая порядок, в котором операции записи выполняются до операций чтения, чтобы свести к минимуму перерасчёт макета. Чтобы передавать данные между этапами, функция этапа может возвращать результат, доступный на следующем этапе.
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.
@Component({
/* ... */
})
export class UserProfile implements OnInit {
ngOnInit() {
/* ... */
}
} Порядок выполнения
На следующих диаграммах показан порядок выполнения хуков жизненного цикла Angular.
Во время инициализации
Последующие обновления
Порядок выполнения директив
Когда вы размещаете одну или несколько директив на том же элементе, что и компонент, в шаблоне или с помощью свойства hostDirectives, платформа не гарантирует какой-либо порядок выполнения заданного хука жизненного цикла между компонентом и директивами на одном элементе. Никогда не полагайтесь на наблюдаемый порядок, поскольку он может измениться в последующих версиях Angular.
Super-powered by Google ©2010–2025.
Code licensed under an MIT-style License. Documentation licensed under CC BY 4.0.
https://angular.dev/guide/components/lifecycle