Crochets de cycle de vie

Un composant a un cycle de vie géré par Angular. Angular le crée, le restitue, crée et restitue ses enfants, le vérifie lorsque ses propriétés liées aux données changent et le détruit avant de le retirer du DOM.

Angular offre des "crochets" de cycle de vie qui offrent une visibilité sur ces moments clés de la vie et la capacité d'agir quand ils se produisent. Une directive a le même ensemble de points d'ancrage de cycle de vie.

Vue d'ensemble des crochets du cycle de vie des composants

Les développeurs peuvent exploiter les moments clés de ce cycle de vie en implémentant une ou plusieurs interfaces de cycle de vie dans la bibliothèque core Angular.

Chaque interface a une seule méthode de raccordement dont le nom correspond au nom d'interface avec le préfixe ng. Par exemple, l'interface OnInit a une méthode de raccordement nommée ngOnInit() qu'Angular appelle peu après la création du composant :

Aucune directive ou composant n'implémentera tous les points d'ancrage du cycle de vie. Angular n'appelle une méthode de raccordement directive / composant que si elle est définie.


Séquence de cycle de vie

Après avoir créé un composant en appelant son constructeur, Angular appelle les méthodes du cycle de vie en suivant la séquence suivante à des moments spécifiques :

Méthode Description
ngOnChanges() Répond lorsque Angular (re)définit les propriétés d'entrée liées aux données. La méthode reçoit un objet SimpleChanges des valeurs de propriété actuelles et précédentes. Appelée avant ngOnInit() et à chaque fois qu'une ou plusieurs propriétés d'entrée liées aux données changent.
ngOnInit() Initialiser la directive/composante après qu'Angular affiche d'abord les propriétés liées aux données et définit les propriétés d'entrée de la directive/composante. Appelé une fois, après le premier ngOnChanges().
ngDoCheck() Détectez et agissez en fonction de changements que Angular ne peut ou ne veut pas détecter seul. Appelé à chaque exécution de détection de changement, immédiatement après ngOnChanges() et ngOnInit().
ngAfterContentInit() Répondez après le contenu externe des projets angulaires à la vue du composant / à la vue dans laquelle se trouve une directive. Appelé une fois après le premier ngDoCheck().
ngAfterContentChecked() Répondre après que Angular vérifie le contenu projeté dans la directive / le composant. Appelé après le ngAfterContentInit() et tous les suivants ngDoCheck().
ngAfterViewInit() Répondre après Angular initialise les vues du composant et les vues enfants / la vue dans laquelle se trouve une directive. Appelé une fois après le premier ngAfterContentChecked().
ngAfterViewChecked() Répondre après Angular vérifie les vues du composant et les vues enfants / la vue dans laquelle se trouve une directive. Appelé après le ngAfterViewInit et tous les suivants ngAfterContentChecked().
ngOnDestroy() Le nettoyage juste avant qu'Angular ne détruise la directive / le composant. Désabonnez Observables et détachez les gestionnaires d'événements pour éviter les fuites de mémoire. Appelé juste avant qu'angular ne détruise la directive / le composant.

Les interfaces sont optionnelles (techniquement)

Les interfaces sont facultatives pour les développeurs JavaScript et Typescript d'un point de vue purement technique. Le langage JavaScript n'a pas d'interfaces. Angular ne peut pas voir les interfaces TypeScript au moment de l'exécution car elles disparaissent du code JavaScript transpilé.

Heureusement, ils ne sont pas nécessaires. Il n'est pas nécessaire d'ajouter les interfaces de hook du cycle de vie aux directives et aux composants pour tirer parti des hooks eux-mêmes.

Au lieu de cela, Angular inspecte les classes de directive et de composant et appelle les méthodes de raccordement si elles sont définies. Les méthodes de recherche et d'appel Angular telles que ngOnInit(), avec ou sans les interfaces.

Néanmoins, il est recommandé d'ajouter des interfaces aux classes de directives TypeScript afin de tirer parti des outils de frappe et d'éditeur puissants.

Autres crochets de cycle de vie angulaire

D'autres sous-systèmes Angular peuvent avoir leurs propres crochets de cycle de vie en dehors de ces crochets de composants.

Les bibliothèques tierces peuvent également implémenter leurs hooks afin de donner aux développeurs plus de contrôle sur la manière dont ces bibliothèques sont utilisées.

Peek-a-boo: tous les crochets

Le Component PeekABoo montre tous les crochets dans un composant. Vous implémenteriez rarement, voire jamais, toutes les interfaces de ce type. Le peek-a-boo existe pour montrer comment Angular appelle les crochets dans l'ordre attendu.

Cet instantané reflète l'état du journal après que l'utilisateur a cliqué sur le bouton "Créer", puis sur le bouton "Détruire"


La séquence des messages du journal suit l'ordre d'appel : OnChanges, OnInit, DoCheck (3x), AfterContentInit, AfterContentChecked (3x), AfterViewInit, AfterViewChecked (3x), et OnDestroy.
Le constructeur n'est pas un crochet Angular en soi. Le journal confirme que les propriétés d'entrée (la propriété name dans ce cas) n'ont aucune valeur affectée à la construction.

Si l'utilisateur avait cliqué sur le bouton "Mettre à jour le héros", le journal afficherait un autre triplet OnChanges et deux autres DoCheck, AfterContentCheckedet et AfterViewChecked.

Les exemples suivants se concentrent sur les détails du crochet.

Espionnage OnInit() et OnDestroy()

Allez sous couverture avec ces deux crochets d'espion pour découvrir quand un élément est initialisé ou détruit. C'est le travail d'infiltration idéal pour une directive.

Faites attention à deux points clés:
  • Les appels Angular décrivent des méthodes pour les directives et les composants.
  • Une directive espion peut fournir un aperçu d'un objet DOM que vous ne pouvez pas modifier directement. De toute évidence, vous ne pouvez pas toucher à la mise en oeuvre d'un natif ‹div›. Vous ne pouvez pas non plus modifier un composant tiers. Mais vous pouvez regarder les deux avec une directive.
La directive d'espionnage est simple, consistant presque entièrement en ngOnInit() et ngOnDestroy() raccroche qui enregistre les messages au parent via un injecté LoggerService.

Vous pouvez appliquer l'espion à n'importe quel élément natif ou composant et il sera initialisé et détruit en même temps que cet élément. Ici, il est attaché au héros répété ‹div› :

La naissance et la mort de chaque espion marque la naissance et la mort du héros attaché ‹div› avec une entrée dans le journal de crochet, comme on peut le voir ici:


L'ajout d'un héros donne naissance à un nouveau héros ‹div›. L'espion ngOnInit() enregistre cet événement. Le bouton "Réinitialiser" efface la heroesliste. Angular supprime tous les ‹div› éléments héros du DOM et détruit leurs directives d'espionnage en même temps. La méthode ngOnDestroy() de l'espion rapporte ses derniers moments.

Les méthodes ngOnInit() et ngOnDestroy() ont des rôles plus vitaux à jouer dans les applications réelles.

OnInit()

Utilisez ngOnInit() pour deux raisons principales :

  • Effectuer des initialisations complexes peu de temps après la construction.
  • Pour configurer le composant après Angular, définissez les propriétés d'entrée.
Les développeurs expérimentés conviennent que les composants devraient être peu coûteux et sûrs à construire.

Ne récupérez pas de données dans un constructeur de composant. Ne craignez pas qu'un nouveau composant essaie de contacter un serveur distant lors de sa création sous test ou avant que vous ne décidiez de l'afficher. Les constructeurs ne devraient pas faire plus que définir les variables locales initiales à des valeurs simples.

Un ngOnInit() est un bon endroit pour qu'un composant récupère ses données initiales.

N'oubliez pas non plus que les propriétés d'entrée liées aux données d'une directive ne sont définies qu'après la construction. C'est un problème si vous devez initialiser la directive en fonction de ces propriétés. Ils auront été définis lors de l'exécution de ngOnInit().

Vous pouvez compter sur Angular pour appeler la méthode ngOnInit() rapidement après la création du composant, c'est là que la logique d'initialisation lourde appartient.

OnDestroy()

Mettez la logique de nettoyage dans ngOnDestroy(), la logique qui doit s'exécuter avant Angular détruit la directive. C'est le moment de notifier une autre partie de l'application que le composant est en train de disparaître.

C'est l'endroit idéal pour libérer des ressources qui ne seront pas automatiquement récupérées. Se désabonner des observables et des événements DOM. Arrêtez les minuteries. Annulez l'enregistrement de tous les rappels que cette directive a enregistrés avec les services globaux ou d'application. Vous risquez des fuites de mémoire si vous négligez de le faire.


OnChanges()

Angular appelle la méthode ngOnChanges() chaque fois qu'elle détecte des modifications des propriétés d'entrée du composant (ou de la directive).

La méthode ngOnChanges() prend un objet qui mappe chaque nom de propriété modifié à un objet SimpleChanges contenant les valeurs de propriété actuelle et précédente. Ce crochet parcourt les propriétés modifiées et les enregistre.

Le composant d'exemple OnChanges, a deux propriétés d'entrée: hero et power.

Le Component hôte parent OnChangesParent se lie à eux comme ceci :

Voici l'exemple en action lorsque l'utilisateur apporte des modifications.



Les entrées du journal apparaissent lorsque la valeur de chaîne de la propriété d'alimentation change. Angular n'appelle le hook que lorsque la valeur de la propriété d'entrée change. La valeur de la propriété hero est la référence à l'objet héros. Angular se moque que la propriété name du héros ait changé. La référence à l'objet héros n'a pas changé, donc, du point de vue d'Angular, il n'y a pas de changement à signaler !

DoCheck()

Utilisez cette méthode pour détecter un changement négligé par Angular..
Ce code inspecte certaines valeurs d'intérêt, en capturant et en comparant leur état actuel avec les valeurs précédentes. Il écrit un message spécial dans le journal lorsqu'il n'y a pas de modifications de fond dans le hero ou le power afin que vous puissiez voir la fréquence de l'appel au ngDoCheck().

Les résultats sont éclairants :



Bien que le crochet ngDoCheck() puisse détecter quand le héros name a changé, il a un coût effroyable. Ce hook est appelé avec une fréquence énorme, après chaque cycle de détection de changement, peu importe où le changement s'est produit. Il est appelé plus de vingt fois dans cet exemple.

La plupart de ces vérifications initiales sont déclenchées par le premier rendu de données d'Angular non liées ailleurs sur la page. Le simple fait de passer dans un autre ‹input› déclenche un appel. Relativement peu d'appels révèlent des modifications réelles des données pertinentes. Il est clair que notre implémentation doit être très légère sinon l'expérience utilisateur en souffre.

AfterView

L'exemple suivant explore les deux méthodes AfterViewInit() et AfterViewChecked() qu'Angular appelle après avoir créé les vues enfant d'un composant. Voici une vue enfant qui affiche le nom d'un héros dans un ‹input› :

ChildComponent

Le Component AfterView affiche cette vue enfant dans son modèle :

AfterViewComponent (modèle)

Les méthodes suivantes agissent en fonction de la modification des valeurs dans la vue enfant, accessible uniquement en interrogeant la vue enfant via la propriété décorée avec @ViewChild.

AfterViewComponent (extraits de classe)

Respecter la règle de flux de données unidirectionnelle

La méthode doSomething() met à jour l'écran lorsque le nom du héros dépasse 10 caractères.
Pourquoi la méthode doSomething() attend-elle avant de mettre à jour ?

La règle de flux de données unidirectionnelle d'Angular interdit les mises à jour de la vue une fois celle-ci composée. Ces deux crochets se déclenchent une fois que la vue du composant a été composée. Angular génère une erreur si le hook met à jour immédiatement la propriété liée au composant. Le Logger Service.tick_then() reporte la mise à jour du journal pour un tour du cycle JavaScript du navigateur.

Voici AfterView en action :



Notez que Angular appelle fréquemment AfterViewChecked(), souvent lorsqu'il n'y a pas de changement d'intérêt. Ecrire des méthodes de crochet maigre pour éviter les problèmes de performance.

Après le contenu

L' exemple AfterContent explore les crochets AfterContentInit() et les appels AfterContentChecked() qu'Angular appelle après le contenu externe de projets Angular dans le composant.

Content projection

La projection de contenu est un moyen d'importer du contenu HTML depuis l'extérieur du composant et d'insérer ce contenu dans le modèle du composant à un emplacement désigné. Les développeurs d'AngularJS connaissent cette technique comme étant une inclusion. Considérez cette variation sur l'exemple AfterView précédent. Cette fois, au lieu d'inclure la vue enfant dans le modèle, le contenu est importé du Component AfterContent parent.

Voici le modèle du parent :
Notez que la balise ‹app-child› est cachée entre les balises ‹after-content›. Ne mettez jamais du contenu entre les balises d'élément d'un composant, sauf si vous avez l'intention de projeter ce contenu dans le composant.

Voici le modèle du composant :

La balise ‹ng-content› est un espace réservé pour le contenu externe. Il indique à Angular où insérer ce contenu. Dans ce cas, le contenu projeté ‹app-child› provient du parent.



Les signes avant-coureurs de la projection de contenu sont doubles :
  • HTML entre les balises d'éléments de composant.
  • La présence de ‹ng-content› balises dans le modèle du composant.

Crochets AfterContent

Les hooks AfterContent sont similaires aux hooks AfterView. La principale différence réside dans le composant enfant.

  • Les points d'ancrage AfterView concernent ViewChildren les composants enfants dont les balises d'élément apparaissent dans le modèle du composant.
  • Les crochets AfterContent concernent les composants enfants ContentChildren qu'Angular a projetés dans le composant.
Les points d'ancrage AfterContent suivants agissent en fonction de la modification des valeurs dans un enfant de contenu, accessible uniquement en les interrogeant via la propriété décorée avec @ContentChild.

Aucun flux unidirectionnel ne vous inquiète avec AfterContent

La méthode doSomething() de ce composant met immédiatement à jour la propriété liée aux données du composant.

Rappelez-vous que Angular appelle les deux points d'ancrage AfterContent avant d'appeler l'un des points d'ancrage AfterView. Angular complète la composition du contenu projeté avant de terminer la composition de la vue de ce composant.