Angular fournit le crochet de cycle de vie ngOnInit
par défaut.
Pourquoi devrions-nous utiliser ngOnInit
, si nous avons déjà un constructeur
?
Angular fournit le crochet de cycle de vie ngOnInit
par défaut.
Pourquoi devrions-nous utiliser ngOnInit
, si nous avons déjà un constructeur
?
Le Constructeur
est une méthode par défaut de la classe qui est exécutée lorsque la classe est instanciée et assure l'initialisation correcte des champs dans la classe et ses sous-classes. Angular, ou mieux Dependency Injector (DI), analyse les paramètres du constructeur et lorsqu'il crée une nouvelle instance en appelant new MyClass()
il essaie de trouver des fournisseurs qui correspondent aux types des paramètres du constructeur, les résout et les passe au constructeur comme
new MyClass(someArg);
ngOnInit
est un crochet de cycle de vie appelé par Angular pour indiquer qu'Angular a fini de créer le composant.
Nous devons importer OnInit
comme ceci afin de l'utiliser (implémenter réellement OnInit
n'est pas obligatoire mais considéré comme une bonne pratique):
import { Component, OnInit } from '@angular/core';
ensuite pour utiliser la méthode OnInit
, nous devons implémenter la classe comme ceci:
export class App implements OnInit {
constructor() {
// Appelé la première fois avant le ngOnInit()
}
ngOnInit() {
// Appelé après le constructeur et après le premier ngOnChanges()
}
}
Implémentez cette interface pour exécuter une logique d'initialisation personnalisée après que les propriétés liées aux données de votre directive ont été initialisées. ngOnInit est appelé juste après que les propriétés liées aux données de la directive aient été vérifiées pour la première fois, et avant que ses enfants aient été vérifiés. Il est invoqué une seule fois lorsque la directive est instanciée.
La plupart du temps nous utilisons ngOnInit
pour toute l'initialisation/déclaration et évitons les manipulations dans le constructeur. Le constructeur ne devrait être utilisé que pour initialiser les membres de classe mais ne devrait pas effectuer 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 là/où les liaisons des composants sont résolues.
Pour plus d'informations, référez-vous ici:
Il est important de noter que les valeurs @Input ne sont pas accessibles dans le constructeur (Merci à @tim pour la suggestion dans les commentaires)
Exactement, la plupart (ou même toutes) des langages basés sur des classes ont des constructeurs pour garantir l'ordre d'initialisation correct surtout pour les classes qui étendent d'autres classes où des problèmes assez compliqués 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é de TypeScript. Les crochets du cycle de vie sont appelés par Angular après qu'une certaine initialisation a eu lieu ou lorsqu'un événement s'est produit pour permettre au composant d'agir dans certaines situations et lui donner la possibilité d'effectuer des tâches aux moments appropriés.
Est-ce qu'il y a une limitation des actions qui peuvent être effectuées sur les constructeurs ?
Je pense que le meilleur exemple serait d'utiliser des services. Disons que je veux récupérer des données de mon serveur lorsque mon composant est 'Activé'. Disons que je veux également faire quelques choses supplémentaires avec les données après les avoir récupérées du serveur, peut-être que j'obtiens une erreur et que je veux la journaliser différemment.
C'est vraiment facile avec ngOnInit par rapport à un constructeur, cela limite également le nombre de couches de rappels que je dois ajouter à mon application.
Par exemple:
export class Utilisateurs implements OnInit{
liste_utilisateurs: Array;
constructor(private _serviceUtilisateur: ServiceUtilisateur){
};
ngOnInit(){
this.getUtilisateurs();
};
getUtilisateurs(){
this._serviceUtilisateur.getUtilisateursDuService().subscribe(utilisateurs => this.liste_utilisateurs = utilisateurs);
};
}
Avec mon constructeur, je pourrais simplement appeler mon _serviceUtilisateur et peupler ma liste_utilisateurs, mais peut-être que je veux faire quelques choses supplémentaires avec. Comme m'assurer que tout est en majuscules, je ne suis pas tout à fait sûr de comment mes données viennent.
Donc, il est beaucoup plus simple d'utiliser ngOnInit.
export class Utilisateurs implements OnInit{
liste_utilisateurs: Array;
constructor(private _serviceUtilisateur: ServiceUtilisateur){
};
ngOnInit(){
this.getUtilisateurs();
};
getUtilisateurs(){
this._serviceUtilisateur.getUtilisateursDuService().subscribe(utilisateurs => this.liste_utilisateurs = utilisateurs);
this.liste_utilisateurs.toUpperCase();
};
}
Il est beaucoup plus facile à voir, donc je n'ai qu'à appeler ma fonction dans mon composant lorsque je l'initialise au lieu de devoir la chercher ailleurs. En réalité, c'est juste un autre outil que vous pouvez utiliser pour le rendre plus facile à lire et à utiliser à l'avenir. De plus, je trouve que c'est vraiment une mauvaise pratique de mettre des appels de fonctions dans un constructeur!
Votre exemple pourrait être simplifié si vous définissiez simplement user_list sur l'Observable. Angular2 a le pipe async, donc il n'y aurait aucun problème là-bas.
@Morgan, juste pour m'apprendre une petite chose ici, pourquoi crées-tu d'abord une fonction getUsers
et ensuite l'insères dans ngOnInit
? N'est-ce pas moins de code juste de l'écrire dans ngOnInit? Je me demande pourquoi les gens font ça de cette façon? Est-ce pour pouvoir réutiliser le code si tu le voulais aussi? Merci.
@AlfaBravo Je suppose que la raison est de donner un sens aux deux lignes à l'intérieur de getUsers()
. De plus, si une troisième ligne était ajoutée à ngOnInit()
sans lien avec les deux lignes existantes, cela pourrait être déroutant pour les futurs mainteneurs.
Le premier (constructeur) est lié à l'instanciation de la 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 la nouvelle instance créée.
Le deuxième correspond à un crochet de cycle de vie des composants Angular2 :
Cité du site officiel d'Angular :
ngOnChanges
est appelé lorsque la valeur d'une liaison d'entrée ou de sortie changengOnInit
est appelé après le premierngOnChanges
Vous devriez donc utiliser ngOnInit
si le traitement d'initialisation repose sur les liaisons du composant (par exemple, les paramètres de composant définis avec @Input
), sinon le constructeur serait suffisant...
Une réponse courte et simple serait la suivante,
Constructeur
: constructeur
est une méthode par défaut
qui s'exécute (par défaut) lors de la construction du composant. Lorsque vous créez une instance
d'une classe à ce moment-là également le constructeur (méthode par défaut)
serait appelé. Donc en d'autres termes, lorsque le composant est en train d'être construit ou/et qu'une instance est créée, le constructeur (méthode par défaut)
est appelé et le code pertinent qui y est écrit est appelé. Fondamentalement et généralement dans Angular2
, il est utilisé pour injecter des éléments comme des services
lorsque le composant est en cours de construction pour une utilisation ultérieure.
OnInit
: ngOnInit est un crochet du cycle de vie du composant qui s'exécute en premier après le constructeur (méthode par défaut)
lorsque le composant est en train d'être initialisé.
Donc, 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 du cycle de vie
Vous pouvez consulter ce petit démo qui montre une implémentation des deux choses.
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 devient effectivement un composant seulement après l'appel du constructeur et après l'initialisation d'Angular.
Hmm, à mon humble avis, c'est toujours la même chose "le constructeur (méthode par défaut) est quelque chose qui est exécuté ou appelé lorsque le composant est construit.". Ce n'est pas seulement appelé lorsque un composant est construit mais aussi pour les services ou lorsque du code comme new MyClass()
est exécuté. Je pense que c'est trompeur de dire que les constructeurs concernent les composants, ils concernent les classes et l'initialisation des instances de ces classes. Un composant est simplement une telle classe. Sinon, je pense que c'est une bonne réponse.
Pour tester cela, j'ai écrit ce code, en m'inspirant du 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("*** Constructeur de la classe User " + msg + " ***");
}
Connexion() {
}
}
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("propriété"); // UN
isLoggingIn:boolean;
constructor() {
this.user = new User("constructeur"); // DEUX
console.log("*** Constructeur du composant de connexion ***");
}
ngOnInit() {
this.user = new User("ngOnInit"); // TROIS
this.user.Connexion();
this.isLoggingIn = true;
console.log("*** ngOnInit du composant de connexion ***");
}
soumettre() {
alert("Vous utilisez : " + this.user.email + " " + this.user.lastLogin);
}
basculerAffichage() {
this.isLoggingIn = !this.isLoggingIn;
}
}
Sortie de la console
JS: *** Constructeur de la classe User propriété ***
JS: *** Constructeur de la classe User constructeur ***
JS: *** Constructeur du composant de connexion ***
JS: *** Constructeur de la classe User ngOnInit ***
JS: *** ngOnInit du composant de connexion ***
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.