В чём разница между 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 => {
// ...
});
}
}