Жизненный цикл компонента
Компонент создаётся, когда его тег появляется на странице, и удаляется, когда тег исчезает — например, когда условие @if стало ложным. На ключевых шагах Angular вызывает методы-хуки с определёнными именами. В них размещают код, который должен выполниться в нужный момент.
Основные хуки
| Хук | Когда вызывается |
|---|---|
constructor | Объект создан, входы ещё не заданы |
ngOnChanges | Изменилось значение входа (и перед ngOnInit) |
ngOnInit | Один раз, после первой установки входов |
ngAfterViewInit | Один раз, когда шаблон компонента выведен |
ngOnDestroy | Перед удалением компонента |
Чаще всего нужны два: ngOnInit для начальной загрузки и ngOnDestroy для уборки.
ngOnInit
Загрузим сохранённые задачи из localStorage, когда список появляется на странице:
// src/app/todo-list/todo-list.ts
import { Component, OnInit, signal } from '@angular/core';
import { Todo } from '../todo';
@Component({
selector: 'app-todo-list',
templateUrl: './todo-list.html',
})
export class TodoList implements OnInit {
todos = signal<Todo[]>([]);
ngOnInit() {
const saved = localStorage.getItem('todos');
if (saved) {
this.todos.set(JSON.parse(saved));
}
}
}Интерфейс OnInit не обязателен, но с ним TypeScript проверит, что имя метода написано правильно. Добавьте задачу, обновите страницу — задача на месте, если в уроке о сигналах вы добавили effect для сохранения.
ngOnDestroy
Таймеры и подписки сами не останавливаются при удалении компонента. Сделаем часы, которые показывают текущее время:
ng generate component clock// src/app/clock/clock.ts
import { Component, OnDestroy, OnInit, signal } from '@angular/core';
@Component({
selector: 'app-clock',
template: `<p>Сейчас {{ time() }}</p>`,
})
export class Clock implements OnInit, OnDestroy {
time = signal(new Date().toLocaleTimeString());
private timerId = 0;
ngOnInit() {
this.timerId = window.setInterval(() => {
this.time.set(new Date().toLocaleTimeString());
}, 1000);
}
ngOnDestroy() {
clearInterval(this.timerId);
}
}Вставьте <app-clock /> в шаблон списка дел и добавьте Clock в imports — время обновляется каждую секунду. Когда компонент исчезнет, ngOnDestroy остановит таймер.
DestroyRef
Уборку можно описать сразу рядом с кодом, который её требует, через inject(DestroyRef):
// src/app/clock/clock.ts
import { Component, DestroyRef, inject, signal } from '@angular/core';
@Component({
selector: 'app-clock',
template: `<p>Сейчас {{ time() }}</p>`,
})
export class Clock {
time = signal(new Date().toLocaleTimeString());
constructor() {
const id = setInterval(() => {
this.time.set(new Date().toLocaleTimeString());
}, 1000);
inject(DestroyRef).onDestroy(() => clearInterval(id));
}
}Результат тот же, но запуск и остановка таймера стоят рядом. Функция inject() подробно разобрана в уроке о сервисах.
Частая ошибка
Читать входное свойство в конструкторе. В этот момент родитель ещё ничего не передал, а обязательный вход input.required() и вовсе выбросит ошибку. Код, которому нужны входы, пишите в ngOnInit или в computed.