Dans Angular, un composant est une directive spéciale, et sa particularité est qu’il possède son propre modèle (html) et son propre style (css). Ainsi, l’utilisation de composants peut rendre notre code très découplé, réutilisable et facilement extensible. Les composantes usuelles sont définies comme suit :
demo.component.ts :
demo.component.html :
demo.component.scss :
Lorsque nous faisons référence au composant, le contenu analysé du composant est rendu :
Supposons qu’il soit nécessaire que le composant accepte du contenu projeté de l’extérieur, ce qui signifie que le composant finit par présenter plus que ce qu’il définit. À ce moment-là, le protagoniste de cet article est inviténg-contenu。
Projection simple
Commençons par la plus simple : ajoutons le demo.component.html modifié et demo.component.scss à demo.component.html, comme suit :
demo.component.html :
demo.component.scss :
Pour l’effet, la couleur de fond du contenant est délibérément définie comme orange.
À ce stade, nous pouvons diffuser du contenu depuis l’extérieur lors de la référence au composant, et le contenu externe sera affiché dans la zone orange :
Projection ciblée
S’il y en a plusieurs en même temps, comment le contenu externe sera-t-il projeté ?
Regardons d’abord un exemple : pour plus de distinction, j’ai ajouté une zone bleue, le demo.component.html modifié et demo.component.scss comme suit :
demo.component.html :
demo.component.scss :
Pour référencer le composant :
À ce stade, nous verrons que le contenu externe est projeté dans la zone bleue :
Bien sûr, si vous placez l’indicatif orange après l’indicatif bleu, alors le contenu externe sera projeté dans la zone orange :
Ainsi, d’après l’exemple ci-dessus, on peut voir que s’il y a aussi un simple , alors le contenu externe sera projeté dans le dernier du modèle de composant.
Ainsi, connaissant ce problème, nous pouvons nous demander : pouvons-nous projeter du contenu externe de manière ciblée ? La réponse est évidemment oui.
Pour gérer cela, soutenez-en unchoisirDes attributs qui permettent de projeter un contenu spécifique à un endroit précis. Cette propriété prend en charge les sélecteurs CSS (sélecteur de balises, sélecteur de classe, sélecteur d’attributs、... ) pour correspondre à ce que tu veux. Si aucun attribut select n’est défini sur ng-content, il recevra le contenu complet, ou le contenu qui ne correspond à aucun autre élément ng-content.
En regardant directement l’exemple, les demo.component.html modifiés et demo.component.scss sont les suivants :
demo.component.html :
demo.component.scss :
Comme vous pouvez le voir dans le code ci-dessus, la zone bleue recevra la partie de l’en-tête de l’etiquetage, la zone rouge recevra la partie de la div avec la classe « demo2 », la zone verte recevra la partie de la div avec le nom de propriété « demo3 », et la zone orange recevra le reste du contenu externe (début, I suis le contenu de l’embed externe, fin).
Pour référencer le composant :
À ce stade, nous verrons le contenu externe projeté dans le fichier spécifié .
Élargir les connaissances
ngProjectAs
Nous savons maintenant que la propriété select de ng-content permet de spécifier que le contenu externe est projeté dans un élément donné .
Pour projeter correctement le contenu basé sur l’attribut select, il existe une limitation : qu’il s’agisse d’un en-tête de balise, d’un div avec la classe « demo2 » ou d’un div avec le nom de propriété « demo3 », ces tags sont tous des sous-nœuds directs de l’étiquette composante.
Que se passerait-il si ce n’était pas un sous-nœud direct ? Modifions simplement le code qui fait référence au composant démo, mettons l’en-tête de tag dans une div, et modifions-le comme suit :
À ce stade, on constate que la partie en-tête d’onglet du contenu n’est plus projetée dans la zone bleue, mais dans la zone orange. La raison est que <ng-content select="header"></ng-content> ne peut pas correspondre à l’en-tête de tag précédent, donc cette partie du contenu est projetée dans la <ng-content></ng-content> zone orange.
Pour résoudre ce problème, nous devons utiliser la propriété ngProjectAs, qui peut être appliquée à n’importe quel élément. Les détails sont les suivants :
En définissant la propriété ngProjectAs, la div où se trouve l’en-tête du tag pointe vers select="header », et la partie de l’en-tête du tag est projetée dans la zone bleue :
<ng-content>Ne « générez » pas de contenu Fais une expérience Pour réaliser une expérience, on définit d’abord un composant démo-enfant-composant :
composant démo à :
Puis dans demo-component cast demo-child-component :
À ce stade, dans la console, on voit que l’initialisation du démo-enfant-composant est terminée ! Ces mots. Mais lorsque nous cliquons sur le bouton pour changer d’opération, l’initialisation du composant enfant de la démonstration est terminée ! Il n’est plus imprimé, ce qui signifie que notre composant demo-child-component n’est instancié qu’une seule fois – jamais détruit et recréé.
Pourquoi cela arrive-t-il ?
Causes d’apparition
<ng-content> Il ne « produit » pas de contenu, il projette simplement du contenu existant. Vous pouvez la considérer comme équivalente à node.appendChild(el) ou à la méthode $(node).append(el) dans jQuery : avec ces méthodes, le nœud n’est pas cloné, il est simplement déplacé à son nouvel emplacement. Par conséquent, le cycle de vie du contenu projeté sera lié à l’endroit où il est déclaré, et non affiché sur place.
Cela explique aussi la question précédente tirée du principe :S’il y en a plusieurs en même temps, comment le contenu externe sera-t-il projeté ?
Ce comportement est appliqué pour deux raisons : la cohérence et la performance. Ce que signifie « cohérence souhaitée » : en tant que développeur, vous pouvez deviner le comportement de votre application à partir de son code. Disons que j’ai écrit le code suivant :
Évidemment, le composant demo-child-component sera instancié une fois, mais maintenant, si nous utilisons un composant issu d’une bibliothèque tierce :
Si une bibliothèque tierce contrôle le cycle de vie d’un composant démo-child, je n’aurai aucun moyen de savoir combien de fois il a été instancié. La seule façon d’y parvenir est d’examiner le code des bibliothèques tierces pour comprendre leur logique de traitement interne. Le sens de lier le cycle de vie d’un composant à nos composants applicatifs plutôt qu’aux wrappers est que les développeurs peuvent contrôler que les compteurs ne sont instanciés qu’une seule fois, sans connaître le code interne des bibliothèques tierces.
Raisons de la performanceest plus important. Comme ng-content n’est qu’un élément mobile, il peut être fait au moment de la compilation, pas à l’exécution, ce qui réduit considérablement la charge de travail de l’application réelle.
Solution de contournement
Pour que le composant contrôle l’instanciation des sous-composants projetés, nous pouvons le faire de deux manières : en utilisant <ng-template> des éléments et ngTemplateOutlets autour de notre contenu, ou en utilisant des directives de structure avec une syntaxe « * ». Pour simplifier, nous utiliserons Syntax dans l’exemple <ng-template> .
composant démo à :
Ensuite, nous incluons demo-child-component dans ng-template :
À ce moment-là, quand on clique sur le bouton pour changer, la console s’imprimeInitialisation du composant enfant démo terminée !Ces mots.
|