Différence entre le constructeur et ngOnInit

1075

Angular fournit un crochet de cycle de vie ngOnInitpar défaut.

Pourquoi devrait ngOnInitêtre utilisé, si nous en avons déjà un constructor?

Haseena PA
la source
11
Hé, consultez ma réponse qui explique la différence du point de vue du fonctionnement interne d'Angular
Max Koretskyi
1
@MaximKoretskyi, votre lien est mort.
Yash Capoor

Réponses:

1112

La Constructorest une méthode par défaut de la classe qui est exécutée lorsque la classe est instanciée et garantit une initialisation correcte des champs dans la classe et ses sous-classes. L'injecteur de dépendance angulaire, ou mieux, analyse les paramètres du constructeur et lorsqu'il crée une nouvelle instance en l'appelant, new MyClass()il essaie de trouver des fournisseurs qui correspondent aux types des paramètres du constructeur, les résout et les transmet au constructeur comme

new MyClass(someArg);

ngOnInit est un hook de cycle de vie appelé par Angular pour indiquer que Angular a terminé la création du composant.

Nous devons importer OnInitcomme ceci pour l'utiliser (en fait, la mise en œuvre OnInitn'est pas obligatoire mais considérée comme une bonne pratique):

import { Component, OnInit } from '@angular/core';

puis pour utiliser make us of the method OnInit, nous devons implémenter la classe comme ceci:

export class App implements OnInit {
  constructor() {
     // Called first time before the ngOnInit()
  }

  ngOnInit() {
     // Called after the constructor and called  after the first ngOnChanges() 
  }
}

Implémentez cette interface pour exécuter la logique d'initialisation personnalisée après l'initialisation des propriétés liées aux données de votre directive. ngOnInit est appelé juste après que les propriétés liées aux données de la directive ont été vérifiées pour la première fois, et avant qu'aucun de ses enfants n'ait été vérifié. Elle n'est invoquée qu'une seule fois lorsque la directive est instanciée.

Généralement, nous utilisons ngOnInitpour toutes les initialisations / déclarations et évitons que les choses fonctionnent dans le constructeur. Le constructeur ne doit être utilisé que pour initialiser les membres de la classe mais ne doit pas faire de "travail" réel.

Vous devez donc utiliser constructor()pour configurer l'injection de dépendance et pas grand-chose d'autre. ngOnInit () est un meilleur endroit pour "démarrer" - c'est où / quand les liaisons des composants sont résolues.

Pour plus d'informations, référez-vous ici:

Pardeep Jain
la source
62
Exactement, la plupart (ou même tous) les langages basés sur les classes ont des constructeurs pour assurer un bon ordre d'initialisation, en particulier des classes qui étendent d'autres classes où des problèmes assez difficiles peuvent survenir, comme les champs finaux (je ne sais pas si TS les a) et similaires. Les constructeurs ne sont pas liés à Angular2, ils sont une fonctionnalité TypeScript. Les hooks du cycle de vie sont appelés par Angular après une initialisation ou lorsqu'un événement s'est produit pour permettre au composant d'agir sur certaines situations et de lui donner la possibilité d'effectuer certaines tâches au bon moment.
Günter Zöchbauer
13
Il y a une citation de bloc dans angular.io/docs/ts/latest/guide/server-communication.html qui explique également ceci: "Les composants sont plus faciles à tester et à déboguer lorsque leurs constructeurs sont simples, et tout travail réel (en particulier appeler un serveur distant) est géré dans une méthode distincte. " - Dans ce cas, cette méthode est la ngOnInit ()
yoonjesung
3
est un hook de cycle de vie appelé par Angular2 pour indiquer que Angular a terminé la création du composant. - ce n'est pas exactement ça. il signale qu'il a initialisé les liaisons. Le composant est créé plus tôt. Voir ma réponse
Max Koretskyi
22
Comme pour toutes les "meilleures pratiques", je pense que ce serait une bonne idée d'expliquer également pourquoi vous ne devriez pas faire de "travail" dans le constructeur. Cet article du responsable de l'équipe Angular est dense mais peut aider: misko.hevery.com/code-reviewers-guide/… En outre, moins d'importance devrait être accordée aux incantations requises pour implémenter OnInit (c'est facile à trouver) et plus sur le fait critique que les liaisons de données ne sont pas disponibles dans le constructeur.
Reikim
2
Si le mode strict est vrai dans un tsconfig.jsonfichier comme "strict": true, vous devez initialiser les membres de la classe dans le constructor, pas dans le ngOnitmême FormGroup.
Rohit Sharma
174

L'article La différence essentielle entre Constructor et ngOnInit dans Angular explore la différence sous plusieurs angles. Cette réponse fournit l'explication de la différence la plus importante liée au processus d'initialisation des composants, qui montre également les différences d'utilisation.

Le processus de bootstrap angulaire comprend les deux étapes principales:

  • construction de l'arborescence des composants
  • exécution de la détection des modifications

Le constructeur du composant est appelé lorsque Angular construit l'arborescence des composants. Tous les hooks du cycle de vie sont appelés dans le cadre de l'exécution de la détection des modifications.

Lorsque Angular construit l'arborescence des composants, l'injecteur du module racine est déjà configuré afin que vous puissiez injecter toutes les dépendances globales. De plus, lorsque Angular instancie une classe de composant enfant, l'injecteur du composant parent est également déjà configuré de sorte que vous pouvez injecter des fournisseurs définis sur le composant parent, y compris le composant parent lui-même. Les constructeurs de composants sont la seule méthode qui est appelée dans le contexte de l'injecteur, donc si vous avez besoin d'une dépendance, c'est le seul endroit pour obtenir ces dépendances.

Lorsque Angular démarre la détection des modifications, l'arborescence des composants est construite et les constructeurs de tous les composants de l'arborescence ont été appelés. Les nœuds de modèle de chaque composant sont également ajoutés au DOM. Le @Inputmécanisme de communication est traité pendant la détection des modifications, vous ne pouvez donc pas vous attendre à ce que les propriétés soient disponibles dans le constructeur. Il sera disponible après ngOnInit.

Voyons un exemple rapide. Supposons que vous ayez le modèle suivant:

<my-app>
   <child-comp [i]='prop'>

Angular démarre donc le démarrage de l'application. Comme je l'ai dit, il crée d'abord des classes pour chaque composant. Il appelle donc MyAppComponentconstructeur. Il crée également un nœud DOM qui est l'élément hôte du my-appcomposant. Il procède ensuite à la création d'un élément hôte pour le constructeur child-compappelant ChildComponent. À ce stade, il n'est pas vraiment concerné par la iliaison d'entrée et les crochets du cycle de vie. Ainsi, lorsque ce processus est terminé, Angular se retrouve avec l'arborescence de vues de composants suivante:

MyAppView
  - MyApp component instance
  - my-app host element data
       ChildCompnentView
         - ChildComponent component instance
         - child-comp host element data  

Ce n'est qu'alors qu'exécute la détection des modifications et met à jour les liaisons pour les my-appappels et ngOnInitsur la classe MyAppComponent. Il procède ensuite à la mise à jour des liaisons pour les child-compappels et ngOnInitsur la classe ChildComponent.

Vous pouvez faire votre logique d'initialisation dans l'un ou l'autre constructeur ou ngOnInitselon ce dont vous avez besoin disponible. Par exemple, l'article Voici comment obtenir ViewContainerRef avant que la requête @ViewChild soit évaluée montre quel type de logique d'initialisation peut être requis pour être exécuté dans le constructeur.

Voici quelques articles qui vous aideront à mieux comprendre le sujet:

Max Koretskyi
la source
33
ce devrait être la réponse acceptée. il explique en fait le POURQUOI plutôt que de répéter des mantras et de les énoncer the constructor should only be used to inject dependencies.
Stavm
1
@ yannick1976, merci! Consultez les articles référencés
Max Koretskyi
@flobacca, pouvez-vous s'il vous plaît reformuler la question, il est difficile de comprendre ce que vous demandez
Max Koretskyi
Corrigez-moi si j'ai tort, s'il-vous plait. J'ai compris que l'arborescence des composants est d'abord construite puis change le processus de détection. Vous avez écrit que le premier constructeur AppComponent est appelé (avec les dépendances résolues) puis le constructeur ChildComponent est appelé (avec les dépendances) puis les liaisons d'entrée pour AppComponent et ensuite OnInit est appelé. Mais ma préoccupation est que si j'ajoute des crochets de cycle de vie aux deux composants, le flux est AppComponentConstructor - -> AppComponentOnInit - → ChildComponentConstructor - → ChildComponentOnInit Pourquoi AppComponentOnInit est appelé avant ChildComponentConstructor
user2485435
1
@MaxKoretskyiakaWizard vous aviez raison. J'ai fait une erreur dans la configuration de mon application. cela fonctionne comme décrit par vous. angular-c7zjsx.stackblitz.io
user2485435
96

Je pense que le meilleur exemple serait d'utiliser les services. Disons que je veux récupérer des données de mon serveur lorsque mon composant est «activé». Disons que je veux aussi faire des choses supplémentaires aux données après les avoir obtenues du serveur, peut-être que je reçois une erreur et que je veux les enregistrer différemment.

C'est vraiment facile avec ngOnInit sur un constructeur, cela limite également le nombre de couches de rappel que je dois ajouter à mon application.

Par exemple:

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);
    };


}

avec mon constructeur, je pourrais simplement appeler mon _userService et remplir ma liste d'utilisateurs, mais peut-être que je veux faire des choses supplémentaires avec. Par exemple, assurez-vous que tout est en majuscules, je ne sais pas exactement comment mes données transitent.

Il est donc beaucoup plus facile d'utiliser ngOnInit.

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();
    };


}

Cela le rend beaucoup plus facile à voir, et donc j'appelle simplement ma fonction dans mon composant lorsque j'initialise au lieu de devoir creuser ailleurs. Vraiment, ce n'est qu'un autre outil que vous pouvez utiliser pour le rendre plus facile à lire et à utiliser à l'avenir. Je trouve aussi que c'est vraiment une mauvaise pratique de mettre des appels de fonction dans un constructeur!

Morgan G
la source
Votre exemple pourrait être simplifié si vous définissez simplement user_list sur Observable. Angular2 a le canal asynchrone, donc il n'y aurait pas de problème là-bas.
DarkNeuron
@Morgan, juste pour moi d'apprendre une petite chose ici, pourquoi créez-vous d'abord une fonction getUserspuis l'insérez-vous dans ngOnInit? N'est-ce pas moins de code que de simplement l'écrire dans ngOnInit? Je me demande encore pourquoi les gens le font de cette façon? Est-ce pour que vous puissiez réutiliser le code si vous le vouliez aussi? Merci.
Alfa Bravo
31
Comme on le voit dans la réponse ci-dessous, cela ne fait aucune différence si c'est dans le constructeur. Ce n'est pas une vraie réponse à l'objectif.
Jimmy Kane
8
Je ne vois pas du tout comment cela répond à la question. Pourquoi ne pourriez-vous pas simplement mettre le code dans le constructor?
CodyBugstein
1
@Morgan pourquoi ne pouvez-vous pas le faireconstructor(private _userService: UserService){ this.getUsers(); };
Ashley
82

OK, tout d'abord ngOnInitfait partie du cycle de vie angulaire , tout en constructorfaisant partie de la classe JavaScript ES6 , donc la différence majeure commence ici! ...

Regardez le tableau ci-dessous que j'ai créé qui montre le cycle de vie d'Angular.

ngOnInit vs constructeur

Dans Angular2 +, nous utilisons constructorpour le faire DI(Dependency Injection)pour nous, tandis que dans Angular 1, cela se produisait en appelant la méthode String et en vérifiant quelle dépendance était injectée.

Comme vous le voyez dans le diagramme ci-dessus, ngOnInitse produit une fois que le constructeur est prêt ngOnChnageset se déclenche une fois que le composant est prêt pour nous. Toute initialisation peut se produire à ce stade, un simple échantillon injecte un service et le paraphe sur init.

OK, je partage également un exemple de code pour que vous puissiez regarder, voir comment nous utilisons ngOnInitet constructordans le code ci-dessous:

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!');
  }
}
Alireza
la source
1
Merci. ce devrait être la meilleure réponse.
Don Dilanga
58

Le premier (constructeur) est lié à l'instanciation de classe et n'a rien à voir avec Angular2. Je veux dire qu'un constructeur peut être utilisé sur n'importe quelle classe. Vous pouvez y mettre un traitement d'initialisation pour l'instance nouvellement créée.

Le second correspond à un hook de cycle de vie des composants Angular2:

Cité sur le site officiel d'angular:

  • ngOnChanges est appelé lorsqu'une valeur de liaison d'entrée ou de sortie change
  • ngOnInit est appelé après le premier ngOnChanges

Vous devez donc utiliser ngOnInitsi le traitement d'initialisation repose sur les liaisons du composant (par exemple les paramètres de composant définis avec @Input), sinon le constructeur suffirait ...

Thierry Templier
la source
49

Je vais juste ajouter une chose importante qui a été ignorée dans les explications ci-dessus et explique quand vous DEVEZ l' utiliser ngOnInit.

Si vous faites une quelconque manipulation du DOM du composant via par exemple ViewChildren , ContentChildren ou ElementRef , vos éléments natifs ne seront pas disponibles pendant la phase du constructeur.

Cependant, puisque ngOnInitcela se produit une fois que le composant a été créé et que les vérifications ( ngOnChanges) ont été appelées, vous pouvez accéder au DOM à ce stade.

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
  }
}
Miroslav Jonas
la source
3
Nan. En @ViewChildrenparticulier, vous devez utiliser la ngAfterViewInitméthode. Voir ici: stackoverflow.com/questions/46314734/…
AsGoodAsItGets
1
Merci, @AsGoodAsItGets de l'avoir signalé. J'ai maintenant amélioré la réponse
Miroslav Jonas
38

Une réponse courte et simple serait:

Constructor: constructorest une default methodexécution ( par sourdult ) lors de la construction du composant. Lorsque vous créez an instanceune classe, ce temps constructor(default method)sera également appelé. En d'autres termes, lorsque le composant est constructed or/and an instance is created constructor(default method)appelé et que le code pertinent écrit à l'intérieur est appelé. Fondamentalement et généralement, Angular2il injectait des choses comme serviceslorsque le composant est en cours de construction pour une utilisation ultérieure.

OnInit: ngOnInit est le hook du cycle de vie du composant qui s'exécute en premier après l' constructor(default method)initialisation du composant.

Ainsi, votre constructeur sera appelé en premier et Oninit sera appelé plus tard après la méthode du constructeur.

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() 
   }
}

Ressources: crochet LifeCycle

Vous pouvez vérifier cette petite démo qui montre l'implémentation des deux choses.

micronyks
la source
5
Je pense que "le constructeur est quelque chose qui s'exécute ou est appelé lorsque le composant est initialisé." est trompeur. Le constructeur est une caractéristique de la classe et non du composant. Je dirais que l'instance de la classe ne devient un composant qu'après l'appel du constructeur et Angular a fait son initialisation.
Günter Zöchbauer
Oui a changé la déclaration que vous pouvez vérifier maintenant.
micronyks
1
Hmm, à mon humble avis c'est toujours le même "constructeur (méthode par défaut) est quelque chose qui s'exécute ou appelé lorsque le composant est construit.". Il est appelé non seulement lorsqu'un composant est construit, mais également pour des services ou lorsque du code similaire new MyClass()est exécuté. Je pense qu'il est trompeur de dire que les constructeurs concernent les composants, ils concernent les classes et l'initialisation des instances de ces classes. Un composant se trouve juste être une telle classe. Sinon, je pense que c'est une bonne réponse.
Günter Zöchbauer
2
Oui absolument. J'ai oublié de mentionner que lorsque vous créez un objet d'une classe, ce temps constructorest également appelé. Mais cette réponse a été écrite dans un contexte angulaire2. Pour connaître la meilleure réponse, vous devez connaître les bases des POO. Je vais quand même mettre à jour la réponse.
micronyks
@ GünterZöchbauer, je ne pense pas que ce soit une affirmation correcte qui soit une caractéristique de la classe et non du composant . Du point de vue du langage de programmation, oui, c'est correct. Mais je peux travailler avec succès avec des composants sans aucun crochet de cycle de vie. Mais je ne peux pas travailler avec un composant sans constructeur si j'ai besoin de DI car c'est le seul endroit injectable. Voir ma réponse
Max Koretskyi
20

Comme beaucoup d'autres langages, vous pouvez initialiser des variables au niveau de la classe, du constructeur ou d'une méthode. C'est au développeur de décider ce qui est le mieux dans son cas particulier. Mais voici une liste des meilleures pratiques en matière de décision.

Variables au niveau de la classe

Habituellement, vous déclarerez ici toutes vos variables qui seront utilisées dans le reste de votre composant. Vous pouvez les initialiser si la valeur ne dépend pas d'autre chose, ou utiliser le mot-clé const pour créer des constantes si elles ne changent pas.

export class TestClass{
    let varA: string = "hello";
}

Constructeur

Normalement, il est préférable de ne rien faire dans le constructeur et de l'utiliser uniquement pour les classes qui seront injectées. La plupart du temps, votre constructeur devrait ressembler à ceci:

   constructor(private http: Http, private customService: CustomService) {}

cela créera automatiquement les variables au niveau de la classe, vous aurez donc accès à customService.myMethod()sans avoir à le faire manuellement.

NgOnInit

NgOnit est un hook de cycle de vie fourni par le framework Angular 2. Votre composant doit implémenterOnInit pour pouvoir l'utiliser. Ce hook de cycle de vie est appelé après l'appel du constructeur et toutes les variables sont initialisées. La majeure partie de votre initialisation devrait aller ici. Vous aurez la certitude qu'Angular a correctement initialisé votre composant et vous pouvez commencer à faire la logique dont vous avez besoin par OnInitrapport à faire des choses lorsque votre composant n'a pas fini de se charger correctement.

Voici une image détaillant l'ordre de ce qui s'appelle:

entrez la description de l'image ici

https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html

TLDR

Si vous utilisez le framework Angular 2 et devez interagir avec certains événements du cycle de vie, utilisez les méthodes fournies par le framework pour éviter les problèmes.

Eduardo Dennis
la source
19

Pour tester cela, j'ai écrit ce code, empruntant au Tutoriel NativeScript :

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;
  }

}

Sortie console

JS: *** User class constructor property ***  
JS: *** User class constructor constructor ***  
JS: *** Login Component Constructor ***  
JS: *** User class constructor ngOnInit ***  
JS: *** Login Component ngOnInit ***  
abbaf33f
la source
18

La principale différence entre le constructeur et ngOnInitest ce que ngOnInitest le crochet du cycle de vie et court après le constructeur. Le modèle interpolé par composant et les valeurs initiales d'entrée ne sont pas disponibles dans le constructeur, mais ils sont disponibles dans ngOnInit.

La différence pratique est de savoir comment ngOnInitaffecte la structure du code. La plupart du code d'initialisation peut être déplacé vers ngOnInit- tant que cela ne crée pas de conditions de concurrence .

Constructeur antipattern

Une quantité importante de code d'initialisation rend la méthode constructeur difficile à étendre, à lire et à tester.

Une recette habituelle pour séparer la logique d'initialisation du constructeur de classe est de la déplacer vers une autre méthode comme init:

class Some {
  constructor() {
    this.init();
  }

  init() {...}
}

ngOnInit peut servir cet objectif dans les composants et les directives:

constructor(
  public foo: Foo,
  /* verbose list of dependencies */
) {
  // time-sensitive initialization code
  this.bar = foo.getBar();
}

ngOnInit() {
  // rest of initialization code
}

Injection de dépendance

Le rôle principal des constructeurs de classes dans Angular est l'injection de dépendances. Les constructeurs sont également utilisés pour l'annotation DI dans TypeScript. Presque toutes les dépendances sont affectées en tant que propriétés à l'instance de classe.

Le constructeur de composant / directive moyen est déjà suffisamment grand car il peut avoir une signature multiligne en raison de dépendances, ce qui met une logique d'initialisation inutile dans le corps du constructeur contribue à l'anti-modèle.

Initialisation asynchrone

Le constructeur d'initialisation asynchrone peut souvent être considéré comme anti-modèle et avoir une odeur car l'instanciation de classe se termine avant la routine asynchrone, ce qui peut créer des conditions de concurrence. Si ce n'est pas le cas, ngOnInitet d'autres crochets de cycle de vie sont de meilleurs endroits pour cela, en particulier parce qu'ils peuvent bénéficier de la asyncsyntaxe:

constructor(
  public foo: Foo,
  public errorHandler: ErrorHandler
) {}

async ngOnInit() {
  try {
    await this.foo.getBar();
    await this.foo.getBazThatDependsOnBar();
  } catch (err) {
    this.errorHandler.handleError(err);
  }
}

S'il y a des conditions de concurrence (y compris celle qu'un composant ne devrait pas apparaître lors d'une erreur d'initialisation), la routine d'initialisation asynchrone doit avoir lieu avant l'instanciation du composant et être déplacée vers le composant parent, la protection du routeur, etc.

Tests unitaires

ngOnInitest plus flexible qu'un constructeur et offre certains avantages pour les tests unitaires qui sont expliqués en détail dans cette réponse .

Étant donné que ce ngOnInitn'est pas appelé automatiquement lors de la compilation des composants dans les tests unitaires, les méthodes qui sont appelées dansngOnInit peuvent être espionnées ou moquées après l'instanciation des composants.

Dans des cas exceptionnels, il ngOnInitpeut être entièrement tronqué pour isoler d'autres unités de composants (par exemple, une logique de modèle).

Héritage

Les classes enfants ne peuvent qu'augmenter les constructeurs, pas les remplacer.

Puisqu'il thisne peut pas être référencé auparavant super(), cela impose des restrictions sur la priorité d'initialisation.

Étant donné que le composant angulaire ou la directive utilise ngOnInitpour la logique d'initialisation insensible au temps, les classes enfants peuvent choisir si elle super.ngOnInit()est appelée et quand:

ngOnInit() {
  this.someMethod();
  super.ngOnInit();
}

Cela serait impossible à implémenter avec le constructeur seul.

Flacon Estus
la source
12

Les réponses ci-dessus ne répondent pas vraiment à cet aspect de la question d'origine: qu'est-ce qu'un crochet de cycle de vie? Il m'a fallu un certain temps pour comprendre ce que cela signifie jusqu'à ce que j'y pense de cette façon.

1) Supposons que votre composant soit un être humain. Les humains ont une vie qui comprend de nombreuses étapes de la vie, puis nous expirons.

2) Notre composant humain pourrait avoir le script de cycle de vie suivant: né, bébé, école primaire, jeune adulte, adulte à mi-âge, adulte senior, mort, éliminé.

3) Dites que vous voulez avoir une fonction pour créer des enfants. Pour éviter que cela ne devienne compliqué et plutôt humoristique, vous voulez que votre fonction ne soit appelée que pendant la phase jeune adulte de la vie de la composante humaine. Vous développez donc un composant qui n'est actif que lorsque le composant parent est au stade Jeune adulte. Les crochets vous aident à le faire en signalant cette étape de la vie et en laissant votre composant agir dessus.

Truc amusant. Si vous laissez votre imagination aller à coder quelque chose comme ça, cela devient compliqué et drôle.

Preston
la source
7

Le constructeur est une méthode en JavaScript et est considéré comme une caractéristique de la classe dans es6. Lorsque la classe est instanciée, elle exécute immédiatement le constructeur, qu'elle soit utilisée dans le cadre Angular ou non. Elle est donc appelée par le moteur JavaScript et Angular n'a pas contrôler cela.

import {Component} from '@angular/core';
@Component({})
class CONSTRUCTORTEST {

//This is called by Javascript not the Angular.
     constructor(){
        console.log("view constructor initialised");
     }
}

La classe "ConstructorTest" est instanciée ci-dessous, elle appelle donc en interne le constructeur (tout cela se fait par JavaScript (es6) no Angular).

new CONSTRUCTORTEST();

C'est pourquoi il existe un hook de cycle de vie ngOnInit dans le rendu Angular.ngOnInit lorsque Angular a terminé l'initialisation du composant.

import {Component} from '@angular/core';
@Component({})
class NGONINITTEST implements onInit{
   constructor(){}
   //ngOnInit calls by Angular
   ngOnInit(){
     console.log("Testing ngOnInit");
   }
}

D'abord, nous instancions la classe comme ci-dessous qui arrive aux exécutions immédiates de la méthode constructeur.

let instance = new NGONINITTEST();

ngOnInit est appelé par Angular si nécessaire comme ci-dessous:

instance.ngOnInit();

Mais vous vous demandez peut-être pourquoi nous utilisons le constructeur dans Angular?

La réponse est des injections de dépendances .Comme il est mentionné précédemment, le constructeur appelle par le moteur JavaScript immédiatement lorsque la classe est instanciée (avant d'appeler ngOnInit par Angular), donc typescript nous aide à obtenir le type des dépendances sont définies dans le constructeur et indique finalement Angulaire quel type de dépendances nous voulons utiliser dans ce composant spécifique.

Negin
la source
7

Deux choses à observer ici:

  1. Le constructeur est appelé chaque fois qu'un objet est créé de cette classe.
  2. ngOnInit appelé une fois le composant créé.

Les deux ont une convivialité différente.

UniCoder
la source
5

constructor () est la méthode par défaut dans le cycle de vie du composant et est utilisé pour l'injection de dépendances. Le constructeur est une fonctionnalité tapuscrit.

ngOnInit () est appelé après le constructeur et ngOnInit est appelé après les premiers ngOnChanges.

c'est à dire:

Constructeur () -->ngOnChanges () -->ngOnInit ()

comme mentionné ci-dessus ngOnChanges()est appelé lorsqu'une valeur de liaison d'entrée ou de sortie change.

Shajin Chandran
la source
4

Les deux méthodes ont des objectifs / responsabilités différents. La tâche du constructeur (qui est une fonctionnalité prise en charge par le langage) est de s'assurer que l'invariant de représentation est respecté. Autrement dit pour vous assurer que l'instance est valide en donnant des valeurs correctes aux membres. C'est au développeur de décider ce que signifie «correct».

La tâche de la méthode onInit () (qui est un concept angulaire) est de permettre des invocations de méthode sur un objet correct (représentation invariante). Chaque méthode doit à son tour s'assurer que l'invariant de représentation est valable à la fin de la méthode.

Le constructeur doit être utilisé pour créer des objets «corrects», la méthode onInit vous donne la possibilité d'appeler des appels de méthode à une instance bien définie.

Bruno Ranschaert
la source
4

Constructeur: La méthode constructeur sur une classe ES6 (ou TypeScript dans ce cas) est une caractéristique d'une classe elle-même, plutôt qu'une caractéristique angulaire. Cela n'est pas sous le contrôle d'Angular lorsque le constructeur est invoqué, ce qui signifie que ce n'est pas un hook approprié pour vous faire savoir quand Angular a fini d'initialiser le composant. Le moteur JavaScript appelle le constructeur, pas directement Angular. C'est pourquoi le hook de cycle de vie ngOnInit (et $ onInit dans AngularJS) a été créé. Gardant cela à l'esprit, il existe un scénario approprié pour utiliser le constructeur. C'est à ce moment que nous voulons utiliser l'injection de dépendances - essentiellement pour «relier» les dépendances au composant.

Comme le constructeur est initialisé par le moteur JavaScript, et TypeScript nous permet d'indiquer à Angular les dépendances dont nous avons besoin pour être mises en correspondance avec une propriété spécifique.

ngOnInit est purement là pour nous indiquer qu'Angular a fini d'initialiser le composant.

Cette phase inclut la première passe à la détection de changement par rapport aux propriétés que nous pouvons lier au composant lui-même - comme l'utilisation d'un décorateur @Input ().

Pour cette raison, les propriétés @Input () sont disponibles dans ngOnInit, mais ne sont pas définies dans le constructeur, par conception

Vishal Gulati
la source
2

Le constructeur est le premier, et cela arrive parfois lorsque les données @input sont nulles! nous utilisons donc Constructor pour déclarer des services et ngOnInit se produit après. Exemple pour contrutor:

 constructor(translate: TranslateService, private oauthService: OAuthService) {
    translate.setDefaultLang('En');
        translate.use('En');}

Exemple pour onInit:

ngOnInit() {
    this.items = [
      { label: 'A', icon: 'fa fa-home', routerLink: ['/'] },
      { label: 'B', icon: 'fa fa-home', routerLink: ['/'] }]
}

Je pense que onInit est comme InitialComponents () dans winForm.

user1012506
la source
1

Dans les cycles de vie angulaires

1) L'injecteur angulaire détecte les paramètres constructeurs et instancie la classe.

2) Cycle de vie du prochain appel angulaire

Crochets de cycle de vie angulaire

ngOnChanges -> Appel de la liaison des paramètres de la directive.

ngOnInit -> Démarrer le rendu angulaire ...

Appelez une autre méthode avec l'état du cycle de vie angulaire.

Shahsavan musulman
la source
1

Le constructorest appelé lorsque Angular "instancie / construit" le composant. La ngOnInitméthode est un hook qui représente la partie d'initialisation du cycle de vie des composants. Une bonne pratique consiste à ne l'utiliser que pour l' injection de services :

constructor(private 
    service1: Service1,
    service2: Service2
){};

Même si c'est possible, vous ne devriez pas faire de "travail" à l'intérieur. Si vous souhaitez lancer une action qui doit se produire lors de l'initialisation du composant, utilisez ngOnInit:

ngOnInit(){
    service1.someWork();
};

De plus, les actions qui impliquent des propriétés d'entrée , provenant d'un composant parent, ne peuvent pas être effectuées dans le constructeur. Ils doivent être placés dans la ngOnInitméthode ou un autre crochet. Il en va de même pour les éléments liés à la vue (le DOM), par exemple les éléments viewchild :

@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
};
veben
la source
0

constructor() est utilisé pour faire l'injection de dépendance.

ngOnInit(), ngOnChanges()Et ngOnDestroy()etc. sont des méthodes du cycle de vie. ngOnChanges()sera le premier à être appelé, avant ngOnInit(), lorsque la valeur d'une propriété liée change, elle ne sera PAS appelée s'il n'y a pas de changement. ngOnDestroy()est appelé lorsque le composant est supprimé. Pour l'utiliser, OnDestroydoit être implementédité par la classe.

xameeramir
la source
1
d'accord, c'est court et clair. Par exemple, constructor () sert à ajouter des objets de service, ngOnInit () sert à manipuler les composants avec les appels de fonction de service nécessaires.
Steve
0

J'ai trouvé la réponse et j'ai essayé de la traduire en anglais: Cette question se posait toujours, même dans les entretiens techniques. En fait, il y a une grande ressemblance entre les deux, mais il y a aussi quelques différences.

  • Le constructeur fait partie d'ECMAScript. D'un autre côté, ngOnInit () est une notion angulaire.

  • Nous pouvons appeler les constructeurs dans toutes les classes même si nous n'utilisons pas Angular

  • LifeCycle: le constructeur est appelé avant ngOnInt ()

  • Dans le constructeur, nous ne pouvons pas appeler d'éléments HTML. Cependant, dans ngOnInit (), nous le pouvons.

  • Généralement, les appels de services dans le ngOnInit () et non dans le constructeur

    Source: http://www.angular-tuto.com/Angular/Component#Diff

doudou
la source
0

Constructeur

La fonction constructeur est fournie avec chaque classe, les constructeurs ne sont pas spécifiques à Angular mais sont des concepts dérivés de conceptions orientées objet. Le constructeur crée une instance de la classe de composants.

OnInit

La ngOnInitfonction est l'une des méthodes de cycle de vie d'un composant angulaire. Les méthodes de cycle de vie (ou hooks) dans les composants angulaires vous permettent d'exécuter un morceau de code à différentes étapes de la vie d'un composant. Contrairement à la méthode constructeur, la ngOnInitméthode provient d'une interface angulaire ( OnInit) que le composant doit implémenter pour utiliser cette méthode. La ngOnInitméthode est appelée peu de temps après la création du composant.

Déc
la source
0

Le constructeur est exécuté lorsque la classe est instanciée. Cela n'a rien à voir avec l'angulaire. C'est la fonction de Javascript et Angular n'en a pas le contrôle

NgOnInit est spécifique à Angular et est appelé lorsque Angular a initialisé le composant avec toutes ses propriétés d'entrée.

Les propriétés @Input sont disponibles sous le hook de cycle de vie ngOnInit. Cela vous aidera à faire des choses d'initialisation comme obtenir des données du serveur principal, etc. pour les afficher dans la vue

Les propriétés @Input sont affichées comme indéfinies dans le constructeur

dasunse
la source
-1

Le constructeur est une fonction exécutée lorsque le composant (ou une autre classe) est construit.

ngOnInit est une fonction appartenant à des groupes de méthodes de cycle de vie d'un composant et ils sont exécutés à un moment différent de notre composant (c'est pourquoi nommer cycle de vie). Voici une liste de tous:

entrez la description de l'image ici Le constructeur sera exécuté avant toute fonction du cycle de vie.

Przemek Struciński
la source