Récemment, alors que j'implémentais une fonctionnalité au travail, j'ai rencontré un petit problème : AngulaireLe composant ne peut pas obtenir l'attribut d'entrée @Input Bien que je sois relativement familier avec ces problèmes, trouver le problème nécessite un processus, donc je le fais toujours. Résumez et notez ce problème.
【Recommandation de tutoriel connexe : "Tutoriel angulaire"】
Je dois définir un attribut d'entrée @Input sur un Component, d'accord, démarrez simplement le code, ce n'est pas difficile.
Le code original est comme ceci :
@Component({ selector: 'my-menu', templateUrl: './main-menu.widget.html' }) export class MyMenuWidget { data: any[]; ... constructor(...) { this._changesSubscription = this._service.changes.pipe( map((data: any[]) => { ... return data; }) ).subscribe((data: any[]) => { this.data = data; }); } ... }
Ajoutez un attribut d'entrée :
@Component({ selector: 'my-menu', templateUrl: './main-menu.widget.html' }) export class MyMenuWidget { @Input() isMainMenu: boolean = false; data: any[]; ... constructor(...) { this._changesSubscription = this._service.changes.pipe( map((data: any[]) => { ... return data; }) ).subscribe((data: any[]) => { if (this.isMainMenu) { this.data = data.filter((d: any) => d.ID === 233); } else { this.data = data; } }); } ... }
Utilisez-le :
<my-menu [isMainMenu]="mainMenu"></my-menu>
Ensuite, j'ai découvert que l'attribut d'entrée isMainMenu dans MyMenuWidget ne peut toujours pas obtenir la valeur, où est l'orthographe ? Je l'ai vérifié et j'ai constaté qu'il n'y avait aucun problème, mais je n'ai tout simplement pas pu obtenir la valeur.
Regardez de plus près, ahhhh ? ? ? , l'abonnement à un Observable est en fait écrit dans le constructeur ! ! ! Bien qu'écrire de cette façon puisse fonctionner normalement dans certains scénarios et n'affecte pas la fonction du code, cette façon d'écrire est très irrégulière, provoquant des problèmes tout comme le code de l'exemple ci-dessus. Par conséquent, dans le processus de développement habituel, il n'est pas recommandé d'écrire ainsi. Alors, quelle est la bonne façon de l'écrire ?
Téléchargez le code.
@Component({ selector: 'my-menu', templateUrl: './main-menu.widget.html' }) export class MyMenuWidget { @Input() isMainMenu: boolean = false; data: any[]; ... constructor(...) { ... } ngOnInit() { this._changesSubscription = this._service.changes.pipe( map((data: any[]) => { ... return data; }) ).subscribe((data: any[]) => { if (this.isMainMenu) { this.data = data.filter((d: any) => d.ID === 233); } else { this.data = data; } }); } ... }
Alors la question est : pourquoi le même code peut-il fonctionner normalement lorsqu'il est placé dans ngOnInit ? Certains diront qu'il faut simplement le mettre dans ngOnInit, mais pas dans le constructeur. Alors pourquoi pas, il faut le comprendre.
La question est : quelle est la différence entre le constructeur angulaire et la fonction ngOnInit ?
Différence de langue :
Examinons d'abord leurs différences du point de vue de la langue. ngOnInit n'est qu'une méthode sur la classe de composant. Sa structure n'est pas différente des autres méthodes de la classe, elle a juste un nom spécifique.
export class MyMenuWidget implements OnInit { ngOnInit() {} }
C'est normal de l'implémenter ou non. Je peux toujours l'écrire comme ça, pas de problème du tout. Aucun balisage explicite n'est nécessaire pour implémenter cette interface.
export class MyMenuWidget { ngOnInit() {} }
Voici comment écrire ES6 Comment écrire le code ci-dessus dans ES5 ?
Le constructeur en est complètement différent. Il sera appelé lors de la création d'une instance de classe.
export class MyMenuWidget { constructor(){} ngOnInit() {} }
Différence dans le processus d'initialisation des composants :
Du point de vue de l'initialisation des composants, la différence entre les deux est toujours très grande. Le processus de démarrage d'Angular comporte deux étapes principales :
1. Construire l'arborescence des composants ; 2. Effectuer la détection des modifications ; Lorsque Angular construit l'arborescence des composants, il doit d'abord créer une instance de composant. créer une instance. C'est-à-dire appeler le constructeur de la classe de composant. Tous les hooks de cycle de vie, y compris ngOnInit, sont ensuite appelés dans le cadre de la phase de détection des changements.
Lorsque Angular démarre la détection des changements, l'arborescence des composants a été construite et les constructeurs de tous les composants de l'arborescence ont été appelés. De plus, le nœud de modèle de chaque composant est ajouté au DOM à ce stade. Ici, vous avez accès à toutes les données dont vous avez besoin pour initialiser le composant – fournisseur DI, DOM, etc. Le mécanisme de communication @Input est géré dans le cadre de la phase de détection des changements, donc @Input n'est pas disponible dans le constructeur.
export class MyMenuWidget { constructor(private _elementRef: ElementRef){ ... } ngOnInit() {} }
Pour Angular
constructor, il est principalement utilisé pour l'initialisation et l'injection de dépendances. L'approche habituelle consiste à mettre le moins de logique possible dans le constructeur. Parfois, même si vous mettez beaucoup de logique, cela n'affecte pas la fonctionnalité. Pour
ngOnInit, Angular crée le DOM du composant, utilise le constructeur pour injecter toutes les dépendances nécessaires et appelle ngOnInit après avoir terminé l'initialisation. C'est un bon endroit pour exécuter la logique d'initialisation du composant. En termes simples
, le constructeurconstructeur lui-même n'a rien à voir avec Angular, ngOnInitces fonctions de hook sont définies dans Angular.
RésuméPour plus de connaissances liées à la programmation, veuillez visiter :
Enseignement de la programmationCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!