Angular bietet standardmäßig einen Lebenszyklus-Hook ngOnInit
.
Warum sollte ngOnInit
verwendet werden, wenn wir bereits eine constructor
haben?
Die Variable Constructor
ist eine Standardmethode der Klasse, die ausgeführt wird, wenn die Klasse instanziiert wird, und sorgt für die korrekte Initialisierung der Felder in der Klasse und ihrer Unterklassen. Angular oder besser Dependency Injector (DI) analysiert die Konstruktorparameter und wenn es eine neue Instanz erstellt, indem es new MyClass()
aufruft, versucht es Anbieter zu finden, die den Typen der Konstruktorparameter entsprechen, löst diese auf und übergibt sie dem Konstruktor ähnlich
new MyClass(someArg);
ngOnInit
ist ein Lebenszyklus-Hook, der von Angular2 aufgerufen wird, um anzuzeigen, dass Angular die Komponente erstellt hat.
Wir müssen OnInit
importieren, um diese Funktion verwenden zu können (die Implementierung von OnInit
ist nicht obligatorisch, wird jedoch als bewährte Methode betrachtet):
import {Component, OnInit} from '@angular/core';
um die Methode von OnInit
zu verwenden, müssen wir diese Klasse in der Klasse implementieren.
export class App implements OnInit{
constructor(){
//called first time before the ngOnInit()
}
ngOnInit(){
//called after the constructor and called after the first ngOnChanges()
}
}
Implementieren Sie diese Schnittstelle, um eine benutzerdefinierte Initialisierungslogik auszuführen, nachdem die datengebundenen Eigenschaften der Direktive initialisiert wurden. ngOnInit wird direkt nach der ersten Prüfung der datengebundenen Eigenschaften der Direktive aufgerufen. und bevor eines seiner Kinder geprüft wurde. Sie wird nur einmal aufgerufen, wenn die Direktive instanziiert wird.
Meistens verwenden wir ngOnInit
für die gesamte Initialisierung/Deklaration und vermeiden, dass etwas im Konstruktor funktioniert. Der Konstruktor sollte nur zum Initialisieren von Klassenmitgliedern verwendet werden, sollte jedoch keine eigentliche "Arbeit" ausführen.
Daher sollten Sie constructor()
verwenden, um Dependency Injection einzurichten, und nicht viel anderes. ngOnInit () ist ein besserer Ort zum "Starten" - dort, wo Komponenten aufgelöst werden.
Weitere Informationen finden Sie hier:
Der Artikel Der wesentliche Unterschied zwischen Constructor und ngOnInit in Angular untersucht den Unterschied aus mehreren Perspektiven. Diese Antwort enthält die wichtigsten Unterschiede, die sich auf den Komponenteninitialisierungsprozess beziehen, und zeigt auch die Unterschiede in der Verwendung.
Der Angular Bootstrap-Prozess besteht aus den zwei Hauptstufen:
Der Konstruktor der Komponente wird aufgerufen, wenn Angular den Komponentenbaum erstellt. Alle Lebenszyklus-Hooks werden als Teil der Änderungslauferkennung aufgerufen.
Wenn Angular einen Komponentenbaum erstellt, ist der Root-Modul-Injektor bereits konfiguriert, sodass Sie globale Abhängigkeiten einfügen können. Wenn Angular eine untergeordnete Komponentenklasse instanziiert, ist auch der Injektor für die übergeordnete Komponente bereits eingerichtet, sodass Sie Anbieter einspritzen können, die für die übergeordnete Komponente definiert sind, einschließlich der übergeordneten Komponente. Komponentenkonstruktoren sind die einzige Methode, die im Kontext des Injektors aufgerufen wird. Wenn Sie also Abhängigkeiten benötigen, können Sie diese Abhängigkeiten nur abrufen.
Wenn Angular die Änderungserkennung startet, wird der Komponentenbaum erstellt und die Konstruktoren für alle Komponenten im Baum wurden aufgerufen. Außerdem werden die Schablonenknoten jeder Komponente zum DOM hinzugefügt. Der @Input
-Kommunikationsmechanismus wird während der Änderungserkennung verarbeitet, sodass Sie nicht erwarten können, dass die Eigenschaften im Konstruktor verfügbar sind. Es wird am nach ngOnInit
verfügbar sein.
Lassen Sie uns ein kurzes Beispiel sehen. Angenommen, Sie haben die folgende Vorlage:
<my-app>
<child-comp [i]='prop'>
Angular startet also das Bootstrapping der Anwendung. Wie gesagt, erstellt es zuerst Klassen für jede Komponente. Es ruft also MyAppComponent
Konstruktor auf. Außerdem wird ein DOM-Knoten erstellt, der das Host-Element der my-app
-Komponente ist. Dann wird ein Host-Element für den Konstruktor child-comp
erstellt und ChildComponent
aufgerufen. In diesem Stadium ist es nicht wirklich mit der i
-Eingabebindung und den Lebenszyklus-Hooks befasst. Nach Abschluss dieses Vorgangs erhält Angular den folgenden Baum der Komponentenansichten:
MyAppView
- MyApp component instance
- my-app Host element data
ChildCompnentView
- ChildComponent component instance
- child-comp Host element data
Erst dann werden Änderungserkennung und Aktualisierungsbindungen für my-app
ausgeführt und ngOnInit
für die MyAppComponent-Klasse aufgerufen. Anschließend werden die Bindungen für child-comp
aktualisiert und ngOnInit
für die ChildComponent-Klasse aufgerufen.
Sie können Ihre Initialisierungslogik entweder im Konstruktor oder in ngOnInit
ausführen, je nachdem, was Sie benötigen. Zum Beispiel im Artikel So erhalten Sie ViewContainerRef, bevor die @ViewChild-Abfrage ausgewertet wird zeigt, welche Art von Initialisierungslogik im Konstruktor ausgeführt werden muss.
Hier einige Artikel, die Ihnen helfen, das Thema besser zu verstehen:
Ich denke, das beste Beispiel wäre die Verwendung von Diensten. Nehmen wir an, ich möchte Daten von meinem Server holen, wenn meine Komponente aktiviert wird. Nehmen wir an, ich möchte noch einige zusätzliche Daten an den Daten vornehmen, nachdem ich sie vom Server erhalten habe. Vielleicht bekomme ich einen Fehler und möchte sie anders protokollieren.
Mit ngOnInit über einen Konstruktor ist es wirklich einfach, es begrenzt auch, wie viele Callback-Layer ich meiner Anwendung hinzufügen muss.
Zum Beispiel:
export class Users implements OnInit{
user_list: Array<any>;
constructor(private _userService: UserService){
};
ngOnInit(){
this.getUsers();
};
getUsers(){
this._userService.getUsersFromService().subscribe(users => this.user_list = users);
};
}
mit meinem Konstruktor könnte ich einfach meinen _userService aufrufen und meine user_list auffüllen, aber vielleicht möchte ich noch ein paar Dinge damit tun. Wenn Sie sicherstellen möchten, dass alles in Großbuchstaben ist, bin ich nicht ganz sicher, wie meine Daten durchkommen.
So wird die Verwendung von ngOnInit wesentlich einfacher.
export class Users implements OnInit{
user_list: Array<any>;
constructor(private _userService: UserService){
};
ngOnInit(){
this.getUsers();
};
getUsers(){
this._userService.getUsersFromService().subscribe(users => this.user_list = users);
this.user_list.toUpperCase();
};
}
Es macht es viel einfacher zu sehen, und deshalb rufe ich meine Funktion einfach in meiner Komponente auf, wenn ich initialisiere, anstatt Dig für eine andere Stelle zu suchen. Es ist wirklich nur ein weiteres Werkzeug, mit dem Sie es in Zukunft leichter lesen und verwenden können. Ich finde es auch sehr schlecht, Funktionsaufrufe in einen Konstruktor zu setzen!
OK, ist zunächst ngOnInit
Teil von Angular Lifecycle, während constructor
Teil von ES6 JavaScript-Klasse ist. Der Hauptunterschied beginnt also hier! ...
Schauen Sie sich das unten erstellte Diagramm an, das den Lebenszyklus von Angular zeigt.
In Angular2 + verwenden wir constructor
, um die DI(Dependency Injection)
für uns zu erledigen, während in Angular 1 der Aufruf der String-Methode erfolgte und die Abhängigkeit geprüft wurde.
Wie Sie im obigen Diagramm sehen, geschieht ngOnInit
, nachdem der Konstruktor fertig ist und ngOnChnages
und gefeuert wird, nachdem die Komponente für uns bereit ist. In dieser Phase kann jede Initialisierung erfolgen. Ein einfaches Beispiel fügt einen Dienst hinzu und initialisiert ihn bei init.
OK, ich teile auch einen Beispielcode für Sie, um zu sehen, wie wir ngOnInit
und constructor
im folgenden Code verwenden:
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'my-app',
template: `<h1>App is running!</h1>
<my-app-main [data]=data></<my-app-main>`,
styles: ['h1 { font-weight: normal; }']
})
class ExampleComponent implements OnInit {
constructor(private router: Router) {} //Dependency injection in the constructor
// ngOnInit, get called after Component initialised!
ngOnInit() {
console.log('Component initialised!');
}
}
Der erste (Konstruktor) bezieht sich auf die Klasseninstanziierung und hat nichts mit Angular2 zu tun. Ich meine, ein Konstruktor kann für jede Klasse verwendet werden. Sie können eine Initialisierungsverarbeitung für die neu erstellte Instanz einfügen.
Der zweite entspricht einem Lebenszyklushaken aus Angular2-Komponenten:
Zitiert von der offiziellen Website von angle:
ngOnChanges
wird aufgerufen, wenn sich ein Eingabe- oder Ausgabebindungswert ändertngOnInit
wird nach der erstenngOnChanges
aufgerufen
Sie sollten also ngOnInit
verwenden, wenn die Initialisierungsverarbeitung auf Bindungen der Komponente angewiesen ist (z. B. mit @Input
definierte Komponentenparameter).
Kurze und einfache Antwort wäre,
Constructor
: constructor
ist ein default method
, der ausgeführt wird (durch Deafult), wenn eine Komponente erstellt wird. Wenn Sie an instance
einer Klasse erstellen, wird zu diesem Zeitpunkt auch constructor(default method)
aufgerufen. Mit anderen Worten, wenn Komponente aufgerufen wird, wird constructed or/and an instance is created constructor(default method)
aufgerufen und der darin enthaltene relevante Code aufgerufen. Grundsätzlich und allgemein in Angular2
wurden Elemente wie services
eingefügt, wenn eine Komponente für die weitere Verwendung erstellt wird.
OnInit
: ngOnInit ist der Lebenszyklus-Hook der Komponente, der nach constructor(default method)
zuerst ausgeführt wird, wenn die Komponente initialisiert wird.
Ihr Konstruktor wird also zuerst aufgerufen und Oninit wird später nach der Konstruktormethode aufgerufen.
boot.ts
import {Cmomponent, OnInit} from 'angular2/core';
import {ExternalService} from '../externalService';
export class app implements OnInit{
constructor(myService:ExternalService)
{
this.myService=myService;
}
ngOnInit(){
// this.myService.someMethod()
}
}
Ressourcen: Lebenszyklushaken
Sie können diese small Demo überprüfen, die die Implementierung beider Dinge zeigt.
Ich werde nur eine wichtige Sache hinzufügen, die in den obigen Erklärungen übersprungen wurde und erklärt, wann ngOnInit
verwenden muss.
Wenn Sie das DOM der Komponente über z. ViewChildren, ContentChildren oder ElementRef, Ihre nativen Elemente sind während der Konstruktorphase nicht verfügbar.
Da jedoch ngOnInit
ausgeführt wird, nachdem die Komponente erstellt und die Prüfungen (ngOnChanges
) aufgerufen wurden, können Sie an dieser Stelle auf das DOM zugreifen.
export class App implements OnInit, AfterViewInit, AfterContentInit {
@Input() myInput: string;
@ViewChild() myTemplate: TemplateRef<any>;
@ContentChild(ChildComponent) myComponent: ChildComponent;
constructor(private elementRef: ElementRef) {
// this.elementRef.nativeElement is undefined here
// this.myInput is undefined here
// this.myTemplate is undefined here
// this.myComponent is undefine here
}
ngOnInit() {
// this.elementRef.nativeElement can be used from here on
// value of this.myInput is passed from parent scope
// this.myTemplate and this.myComponent are still undefined
}
ngAfterContentInit() {
// this.myComponent now gets projected in and can be accessed
// this.myTemplate is still undefined
}
ngAfterViewInit() {
// this.myTemplate can be used now as well
}
}
Um dies zu testen, habe ich diesen Code geschrieben und aus dem NativeScript Tutorial entlehnt:
user.ts
export class User {
email: string;
password: string;
lastLogin: Date;
constructor(msg:string) {
this.email = "";
this.password = "";
this.lastLogin = new Date();
console.log("*** User class constructor " + msg + " ***");
}
Login() {
}
}
login.component.ts
import {Component} from "@angular/core";
import {User} from "./../../shared/user/user"
@Component({
selector: "login-component",
templateUrl: "pages/login/login.html",
styleUrls: ["pages/login/login-common.css", "pages/login/login.css"]
})
export class LoginComponent {
user: User = new User("property"); // ONE
isLoggingIn:boolean;
constructor() {
this.user = new User("constructor"); // TWO
console.log("*** Login Component Constructor ***");
}
ngOnInit() {
this.user = new User("ngOnInit"); // THREE
this.user.Login();
this.isLoggingIn = true;
console.log("*** Login Component ngOnInit ***");
}
submit() {
alert("You’re using: " + this.user.email + " " + this.user.lastLogin);
}
toggleDisplay() {
this.isLoggingIn = !this.isLoggingIn;
}
}
Konsolenausgabe
JS: *** User class constructor property ***
JS: *** User class constructor constructor ***
JS: *** Login Component Constructor ***
JS: *** User class constructor ngOnInit ***
JS: *** Login Component ngOnInit ***
Der Hauptunterschied zwischen Konstruktor und ngOnInit
besteht darin, dass ngOnInit
Lebenszyklus-Hook ist und nach Konstruktor ausgeführt wird. Komponenten-interpolierte Vorlagen- und Eingabe-Anfangswerte sind im Konstruktor nicht verfügbar, jedoch in ngOnInit
.
Der praktische Unterschied ist, wie ngOnInit
die Struktur des Codes beeinflusst. Die meisten Initialisierungscodes können nach ngOnInit
- verschoben werden, sofern dadurch keine Race-Bedingungen erstellt werden.
Eine beträchtliche Menge an Initialisierungscode macht es schwierig, die Konstruktormethode zu erweitern, zu lesen und zu testen.
Ein übliches Rezept zum Trennen der Initialisierungslogik vom Klassenkonstruktor ist das Verschieben in eine andere Methode wie init
:
class Some {
constructor() {
this.init();
}
init() {...}
}
ngOnInit
kann diesen Zweck in Komponenten und Anweisungen erfüllen:
constructor(
public foo: Foo,
/* verbose list of dependencies */
) {
// time-sensitive initialization code
this.bar = foo.getBar();
}
ngOnInit() {
// rest of initialization code
}
Die primäre Rolle von Klassenkonstruktoren in Angular ist die Abhängigkeitsinjektion. Konstruktoren werden auch für DI-Annotationen in TypeScript verwendet. Fast alle Abhängigkeiten werden der Klasseninstanz als Eigenschaften zugewiesen.
Ein durchschnittlicher Konstruktor für Komponenten/Anweisungen ist bereits groß genug, da er aufgrund von Abhängigkeiten eine mehrzeilige Signatur aufweisen kann. Dies trägt dazu bei, dass eine unnötige Initialisierungslogik in den Konstruktorkörper eingefügt wird.
Konstruktor für asynchrone Initialisierung kann oft als Antipattern und als Geruch angesehen werden, da die Klasseninstanziierung beendet wird, bevor die asynchrone Routine ausgeführt wird. Dies kann zu Race-Bedingungen führen. Wenn dies nicht der Fall ist, sind ngOnInit
und andere Lebenszyklus-Hooks dafür bessere Orte, insbesondere, weil sie von der async
-Syntax profitieren können:
constructor(
public foo: Foo,
public errorHandler: ErrorHandler
) {}
async ngOnInit() {
try {
await this.foo.getBar();
await this.foo.getBazThatDependsOnBar();
} catch (err) {
this.errorHandler.handleError(err);
}
}
Wenn Race-Bedingungen vorliegen (einschließlich der Bedingung, dass eine Komponente bei einem Initialisierungsfehler nicht angezeigt werden sollte), sollte eine asynchrone Initialisierungsroutine vor der Instantiierung der Komponenten stattfinden und zur übergeordneten Komponente, zum Router-Guard usw. verschoben werden.
ngOnInit
ist flexibler als ein Konstruktor und bietet einige Vorteile für Komponententests, die ausführlich in diese Antwort erläutert werden.
In Anbetracht dessen, dass ngOnInit
bei Komponententests in Komponententests nicht automatisch aufgerufen wird, können Methoden, die in ngOnInit
aufgerufen werden, nach der Instanziierung von Komponenten ausspioniert oder gemustert werden.
In Ausnahmefällen kann ngOnInit
vollständig überbrückt werden, um andere Komponenteneinheiten zu isolieren (z. B. einige Vorlagenlogik).
Untergeordnete Klassen können Konstruktoren nur erweitern, nicht ersetzen.
Da this
nicht vor super()
referenziert werden kann, sind die Initialisierungsvorgaben eingeschränkt.
In Anbetracht dessen, dass die Angular-Komponente oder -Direktive ngOnInit
für zeitunabhängige Initialisierungslogik verwendet, können untergeordnete Klassen auswählen, ob super.ngOnInit()
aufgerufen wird und wann:
ngOnInit() {
this.someMethod();
super.ngOnInit();
}
Dies ist mit dem Konstruktor alleine nicht zu implementieren.
Wie viele andere Sprachen können Sie Variablen auf Klassenebene, im Konstruktor oder in einer Methode initialisieren. Es ist Sache des Entwicklers, zu entscheiden, was in seinem speziellen Fall am besten ist. Nachfolgend finden Sie eine Liste mit Best Practices für die Entscheidungsfindung.
In der Regel werden Sie hier alle Variablen deklarieren, die in der restlichen Komponente verwendet werden. Sie können sie initialisieren, wenn der Wert nicht von etwas anderem abhängt, oder das Schlüsselwort const zum Erstellen von Konstanten verwenden, wenn sich diese nicht ändern.
export class TestClass{
let varA: string = "hello";
}
Normalerweise empfiehlt es sich, im Konstruktor nichts zu tun und nur für Klassen zu verwenden, die eingefügt werden sollen. In der Regel sollte Ihr Konstruktor so aussehen:
constructor(private http: Http, private customService: CustomService) {}
dadurch werden die Klassenebenenvariablen automatisch erstellt, sodass Sie auf customService.myMethod()
zugreifen können, ohne dass Sie dies manuell vornehmen müssen.
NgOnit ist ein Lebenszyklus-Hook, der vom Angular 2-Framework bereitgestellt wird. Ihre Komponente muss OnInit
implementieren, um sie verwenden zu können. Dieser Lebenszyklus-Hook wird aufgerufen, nachdem der Konstruktor aufgerufen wurde und alle Variablen initialisiert wurden. Der Großteil Ihrer Initialisierung sollte hier hingehen. Sie haben die Gewissheit, dass Angular Ihre Komponente korrekt initialisiert hat, und Sie können damit beginnen, die erforderliche Logik in OnInit
auszuführen, anstatt Dinge zu tun, wenn Ihre Komponente nicht ordnungsgemäß geladen wurde.
Hier ist ein Bild, das die Reihenfolge des Aufrufs beschreibt:
https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html
Wenn Sie das Angular 2-Framework verwenden und mit bestimmten Lebenszyklusereignissen interagieren müssen, verwenden Sie die vom Framework dafür bereitgestellten Methoden, um Probleme zu vermeiden.
Die obigen Antworten beantworten diesen Aspekt der ursprünglichen Frage nicht wirklich: Was ist ein Lebenszyklushaken? Ich habe eine Weile gebraucht, um zu verstehen, was das bedeutet, bis ich so darüber nachgedacht habe.
1) Angenommen, Ihre Komponente ist ein Mensch. Menschen haben ein Leben, das viele Lebensabschnitte umfasst, und dann verfallen wir.
2) Unsere menschliche Komponente könnte das folgende Lebenszyklus-Skript haben: Geboren, Baby, Grundschule, junger Erwachsener, Erwachsener mittleren Alters, älterer Erwachsener, tot, entsorgt.
3) Angenommen, Sie möchten eine Funktion zum Erstellen von Kindern haben. Um zu verhindern, dass dies kompliziert und eher humorvoll wird, möchten Sie, dass Ihre Funktion nur im Stadium des jungen Erwachsenen des menschlichen Komponentenlebens aufgerufen wird. Sie entwickeln also eine Komponente, die nur aktiv ist, wenn sich die übergeordnete Komponente im Stadium des jungen Erwachsenen befindet. Hooks helfen Ihnen dabei, indem Sie diesen Lebensabschnitt signalisieren und Ihre Komponente darauf einwirken lassen.
Lustige Sachen. Wenn Sie Ihre Phantasie tatsächlich dazu verwenden, so etwas zu codieren, wird es kompliziert und lustig.
Derconstructorist eine Methode in JavaScript und wird als ein Feature der Klasse in es6 betrachtet. Wenn die Klasse instanziiert wird, führt sie den Konstruktor sofort aus, unabhängig davon, ob sie im Angular-Framework verwendet wird oder nicht von JavaScript-Engine aufgerufen und Angular hat keine Kontrolle darüber.
import {Component} from '@angular/core';
@Component({})
class CONSTRUCTORTEST {
//This is called by Javascript not the Angular.
constructor(){
console.log("view constructor initialised");
}
}
Die "ConstructorTest" -Klasse wird unten instanziiert. Sie ruft intern den -Konstruktor auf (All dies geschieht durch JavaScript (es6) und kein Angular).
new CONSTRUCTORTEST();
Deshalb gibt es in Angular.ngOnInit den RendererngOnInitlifecycle, wenn Angular die Initialisierung der Komponente abgeschlossen hat.
import {Component} from '@angular/core';
@Component({})
class NGONINITTEST implements onInit{
constructor(){}
//ngOnInit calls by Angular
ngOnInit(){
console.log("Testing ngOnInit");
}
}
Zuerst instanziieren wir die Klasse wie folgt, die unmittelbar zur Ausführung der Konstruktormethode führt.
let instance = new NGONINITTEST();
ngOnInit wird von Angular bei Bedarf wie folgt aufgerufen:
instance.ngOnInit();
Aber Sie fragen sich vielleicht, warum wir in Angular einen Konstruktor verwenden?
Die Antwort istDependencies injections. Wie bereits erwähnt, ruft der Konstruktor die JavaScript-Engine sofort auf, wenn die Klasse instanziiert wird (bevor ngOnInit von Angular aufgerufen wird), daher hilft TypeScript, den Typ der Abhängigkeiten zu ermitteln sind im Konstruktor definiert und geben Angular schließlich an, welche Art von Abhängigkeiten wir in dieser spezifischen Komponente verwenden möchten.
Zwei Dinge, die hier zu beachten sind:
Beide haben unterschiedliche Verwendbarkeit.
Konstruktor: Die Konstruktormethode für eine ES6-Klasse (oder in diesem Fall TypeScript) ist ein Feature einer Klasse selbst und nicht ein Angular-Feature. Es liegt außerhalb des Einflussbereichs von Angular, wenn der Konstruktor aufgerufen wird. Dies bedeutet, dass es kein geeigneter Haken ist, um Sie darüber zu informieren, wann Angular die Initialisierung der Komponente abgeschlossen hat. Die JavaScript-Engine ruft den Konstruktor auf, nicht direkt Angular. Aus diesem Grund wurde der Lebenszyklus-Hook ngOnInit (und $ onInit in AngularJS) erstellt. Vor diesem Hintergrund gibt es ein geeignetes Szenario für die Verwendung des Konstruktors. In diesem Fall möchten wir die Abhängigkeitseinspritzung nutzen - im Wesentlichen für die "Verdrahtung" von Abhängigkeiten in der Komponente.
Da der Konstruktor von der JavaScript-Engine initialisiert wird und TypeScript es ermöglicht, Angular mitzuteilen, welche Abhängigkeiten wir einer bestimmten Eigenschaft zuordnen müssen.
ngOnInit gibt uns nur ein Signal, dass Angular die Initialisierung der Komponente abgeschlossen hat.
Diese Phase umfasst den ersten Durchgang bei der Änderungserkennung gegen die Eigenschaften, die wir möglicherweise an die Komponente selbst binden können, z. B. die Verwendung eines @Input () - Dekorators.
Aus diesem Grund sind die @Input () - Eigenschaften in ngOnInit verfügbar, im Konstruktor jedoch nicht definiert
Beide Methoden haben unterschiedliche Ziele/Verantwortlichkeiten. Die Aufgabe des Konstruktors (der eine sprachgestützte Funktion ist) besteht darin, sicherzustellen, dass die Repräsentationsinvariante gilt. Andernfalls wird angegeben, dass die Instanz gültig ist, indem den Mitgliedern korrekte Werte angegeben werden. Es ist Sache des Entwicklers, zu entscheiden, was "richtig" bedeutet.
Die Aufgabe der Methode onInit () (die ein Winkelkonzept ist) besteht darin, Methodenaufrufe für ein korrektes Objekt (Darstellungsinvariante) zuzulassen. Jede Methode sollte wiederum sicherstellen, dass die Repräsentationsinvariante gilt, wenn die Methode beendet wird.
Der Konstruktor sollte verwendet werden, um 'korrekte' Objekte zu erstellen. Die onInit-Methode gibt Ihnen die Möglichkeit, Methodenaufrufe an einer genau definierten Instanz aufzurufen.
constructor () ist die Standardmethode im Komponentenlebenszyklus und wird für die Abhängigkeitsinjektion verwendet. Konstruktor ist eine TypeScript-Funktion.
ngOnInit () wird nach dem Konstruktor und ngOnInit nach dem ersten ngOnChanges aufgerufen.
d. h. Konstruktor () -> ngOnChanges () -> ngOnInit ()
wie oben erwähnt, wird ngOnChanges () aufgerufen, wenn sich ein Eingabe- oder Ausgabebindungswert ändert.
Konstruktor ist der erste, und es kommt manchmal vor, wenn @input -Daten null!
constructor(translate: TranslateService, private oauthService: OAuthService) {
translate.setDefaultLang('En');
translate.use('En');}
Beispiel für onInit:
ngOnInit() {
this.items = [
{ label: 'A', icon: 'fa fa-home', routerLink: ['/'] },
{ label: 'B', icon: 'fa fa-home', routerLink: ['/'] }]
}
Ich denke, dass onInit mit InitialComponents () in WinForm vergleichbar ist.
Ich habe die Antwort gefunden und versucht, sie ins Englische zu übersetzen: Diese Frage ist auch in technischen Interviews noch aufgetaucht. In der Tat gibt es eine große Ähnlichkeit zwischen den beiden, aber es gibt auch einige Unterschiede.
Der Konstruktor ist Teil von ECMAScript. Andererseits ist ngOnInit () ein Begriff von eckig.
Wir können die Konstruktoren in allen Klassen aufrufen, auch wenn wir Angular nicht verwenden
LifeCycle: Der Konstruktor wird vor ngOnInt () aufgerufen
Im Konstruktor können wir keine HTML-Elemente aufrufen. In ngOnInit () ist dies jedoch möglich.
Generell Aufrufe von Diensten im ngOnInit () und nicht im Konstruktor
Eigentlich ngOnInit () aus zwei Hauptgründen:
1) Komplexe Initialisierungen kurz nach der Erstellung durchführen.
2) Um die Komponente einzurichten, nachdem Angular die Eingabeeigenschaften festgelegt hat.
Erfahrene Entwickler sind sich einig, dass Komponenten billig und sicher zu bauen sein sollten.
Misko Hevery, Angular Teamleiter, erklärt, warum Sie komplexe Konstruktorlogik vermeiden sollten.
Rufen Sie keine Daten in einem Komponentenkonstruktor ab. Sie sollten sich keine Sorgen machen, dass eine neue Komponente versucht, einen Remoteserver zu kontaktieren, wenn sie im Test erstellt wird oder bevor Sie sich entscheiden, ihn anzuzeigen. Konstruktoren sollten nicht mehr tun, als die anfänglichen lokalen Variablen auf einfache Werte zu setzen.
Ein ngOnInit () ist ein guter Ort, an dem eine Komponente ihre Anfangsdaten abrufen kann.
Denken Sie auch daran, dass die datengebundenen Eingabeeigenschaften einer Direktive erst nach der Erstellung festgelegt werden. Dies ist ein Problem, wenn Sie die Direktive basierend auf diesen Eigenschaften initialisieren müssen. Sie werden festgelegt, wenn ngOnInit () ausgeführt wird.
Die Methode ngOnChanges () ist Ihre erste Möglichkeit, auf diese Eigenschaften zuzugreifen. Angular ruft ngOnChanges () vor ngOnInit () und viele Male danach auf. NgOnInit () wird nur einmal aufgerufen.
Sie können sich darauf verlassen, dass Angular die Methode ngOnInit () kurz nach dem Erstellen der Komponente aufruft. Dort gehört die schwere Initialisierungslogik hin.
Konstruktor Ein Klassenkonstruktor in Angular wird hauptsächlich zum Einfügen von Abhängigkeiten verwendet. Angular ruft dieses Konstruktorinjektionsmuster auf, das hier ausführlich erläutert wird. Für detailliertere Einblicke in die Architektur können Sie Constructor Injection vs. Setter Injection von Miško Hevery lesen.
Die Verwendung eines Konstruktors ist jedoch nicht auf DI beschränkt. Die Router-Outlet-Direktive des @ angle/router-Moduls registriert sich selbst und seinen Standort (viewContainerRef) im Router-Ökosystem. Ich habe diesen Ansatz unter Hier erfahren Sie, wie Sie ViewContainerRef abrufen, bevor die @ViewChild-Abfrage ausgewertet wird.
Die übliche Praxis ist jedoch so wenig Logik wie möglich in Konstruktoren.
NgOnInit Wie wir oben erfahren haben, wenn Angular ngOnInit aufruft, wurde die Erstellung eines Komponenten-DOMs abgeschlossen und alle erforderlichen Abhängigkeiten über den Konstruktor injiziert und Eingabebindungen verarbeitet. Hier haben Sie also alle erforderlichen Informationen zur Verfügung, die es zu einem guten Ort für die Durchführung der Initialisierungslogik machen.
Es ist eine gängige Praxis, ngOnInit zur Durchführung der Initialisierungslogik zu verwenden, auch wenn diese Logik nicht von DI-, DOM- oder Eingabebindungen abhängt.
In den Angular Lebenszyklen
1) Winkeleinspritzventil erkennt Konstruktorparameter und instanziiert die Klasse.
2) Nächster Lebenszyklus des Winkelrufs
ngOnChanges -> Aufruf der Direktiven Parameterbindung.
ngOnInit -> Winkel-Rendering starten ...
Rufen Sie eine andere Methode mit dem Status des Winkellebenszyklus auf.
Die Variable constructor
wird aufgerufen, wenn Angular die Komponente "instanziiert/konstruiert". Die Methode ngOnInit
ist ein Hook, der den Initialisierungsteil des Komponentenlebenszyklus darstellt. Eine bewährte Methode ist, sie nur für Service-Injection) zu verwenden:
constructor(private
service1: Service1,
service2: Service2
){};
Selbst wenn es möglich ist, sollten Sie keine "Arbeit" im Inneren ausführen. Wenn Sie eine Aktion starten möchten, die bei der Komponente "Initialisierung" ausgeführt werden muss, verwenden Sie ngOnInit
:
ngOnInit(){
service1.someWork();
};
Darüber hinaus können Aktionen, die Eingabeeigenschaften betreffen und von einer übergeordneten Komponente stammen, nicht im Konstruktor ..__ ausgeführt werden. Sie sollten in der ngOnInit
-Methode oder einem anderen Hook ..__ abgelegt werden für ein Element, das sich auf die Sicht bezieht (das DOM), zum Beispiel Viewchild-Elemente:
@Input itemFromParent: string;
@ViewChild('childView') childView;
constructor(){
console.log(itemFromParent); // KO
// childView is undefined here
};
ngOnInit(){
console.log(itemFromParent); // OK
// childView is undefined here, you can manipulate here
};
Konstruktor ist eine Funktion, die ausgeführt wird, wenn eine Komponente (oder eine andere Klasse) erstellt wird.
ngOnInit ist eine Funktion, die zu einer Methodengruppe für den Komponentenlebenszyklus gehört. Sie wird zu einem anderen Zeitpunkt unserer Komponente ausgeführt (daher Name Lifecycle). . Hier ist eine Liste von allen:
Der Konstruktor wird vor jeder Lebenszyklusfunktion ausgeführt.
constructor()
wird zur Abhängigkeitsinjektion verwendet.
ngOnInit()
, ngOnChanges()
und ngOnDestroy()
etc. sind Lebenszyklusmethoden. ngOnChanges()
ist der erste Aufruf vor ngOnInit()
. Wenn sich der Wert einer gebundenen Eigenschaft ändert, wird er NICHT aufgerufen, wenn keine Änderung vorliegt. ngOnDestroy()
wird aufgerufen, wenn die Komponente entfernt wird. Um es zu verwenden, muss OnDestroy
von der Klasse implement
ed sein.