В чём разница между constructor() и ngOnInit()?
На первый взгляд, оба метода вызываются при создании компонента, но их назначение и место в жизненном цикле приложения существенно различаются.
Конструктор – это стандартная часть языка TypeScript/JavaScript, а ngOnInit
– это специальный метод, который Angular вызывает как часть своего lifecycle (жизненного цикла).
При создании экземпляра класса (компонента) Angular вызывает его конструктор и передаёт в него все необходимые DI зависимости (сервисы, указанные в параметрах конструктора). То есть уже на этапе конструктора вы можете обратиться к своим сервисам и вызвать у них нужные методы. Однако @Input()ы
компонента могут ещё не быть инициализированы. Именно поэтому при прохождении код-ревью часть обращают внимание именно на логику внутри конструктора.
Метод ngOnInit
запускается после инициализации всех входных свойств. Это значит, что компоненту будут доступны все данные из родительских компонентов, и Angular уже совершил все необходимые привязки данных Поэтому основную бизнес-логику инициализации (например, подгрузку данных, настройку подписок на сервисы и работу со значениями @Input()
) чаще всего размещают именно внутри ngOnInit
.
import { Component, OnInit, Input } from '@angular/core'; import { MyService } from './my.service'; @Component({ selector: 'app-my-component', template: ` <h1>Hello, {{ userName }}!</h1> ` }) export class MyComponent implements OnInit { @Input() userName!: string; constructor(private myService: MyService) { // Здесь DI уже сработал, и myService доступен. // Но значению @Input() userName ещё может не быть присвоено фактическое значение. console.log('constructor:', this.userName); // Скорее всего здесь будет undefined } ngOnInit(): void { // На момент вызова ngOnInit все входные свойства уже инициализированы. console.log('ngOnInit:', this.userName); // Здесь уже будет фактическое значение // Здесь обычно размещают код инициализации, например подписки на сервисы или подготовку данных this.myService.loadData(this.userName).subscribe(data => { // ... }); } }