Points clés
$onInit
et $onDestroy
pour gérer efficacement les paramètres et le démontage des composants pour garantir que les ressources sont correctement initialisées et nettoyées. $scope
, ce qui est conforme aux pratiques angulaires 2 et améliore la modularité et la réusabilité des composants. Cet article a été examiné par Mark Brown et Jurgen Van de Moere. Merci à tous les pairs examinateurs de SitePoint pour avoir obtenu le contenu de SitePoint à son meilleur!
10 janvier 2017: L'article mis à jour, a clarifié la section sur la liaison à sens unique et les informations ajoutées sur la liaison à des heures. ---
Dans Angular 1, les composants sont les mécanismes de création d'éléments HTML personnalisés. Cela a été possible dans le passé avec les directives angulaires, mais les composants s'appuient sur diverses améliorations à Angular et appliquent les meilleures pratiques en matière de construction et de conception.
Dans cet article, nous plongerons dans la conception des composants et comment les utiliser dans votre application. Si vous n'avez pas commencé à utiliser des composants dans Angular 1, vous pouvez lire notre récent tutoriel sur leur syntaxe et leur conception. Mon objectif est de décrire les meilleures pratiques qui amélioreront la qualité de votre application.
Il convient également de noter que de nombreuses meilleures pratiques pour Angular 2 ont été introduites dans Angular 1 via la nouvelle API composante, vous permettant de créer des applications plus faciles à refacter plus tard. Angular 2 influence la façon dont nous pensons et concevons les composants angulaires 1, mais il existe encore de nombreuses différences évidentes. Angular 1 est toujours un outil très puissant pour créer des applications, donc je crois que même si vous n'allez pas ou si vous n'êtes pas prêt à migrer vers Angular 2, il vaut la peine d'investir dans l'utilisation des composants pour améliorer votre application.
doivent être conçus avec de nombreuses fonctionnalités clés à l'esprit pour en faire un puissant bloc de construction pour les applications. Nous explorerons chaque fonctionnalité plus en détail, mais voici les principaux concepts que les composants devraient suivre.
Laissez-nous maintenant comprendre pourquoi et comment isoler et encapsuler les composants du reste de l'application.
L'évolution de la fonctionnalité angulaire 1 est de permettre des composants isolés et encapsulés, pour une bonne raison. Certaines applications précoces étaient fortement associées à l'utilisation de $scope
et des contrôleurs imbriqués. Initialement, Angular n'a pas fourni de solution, mais maintenant il l'a.
Les bons composants n'exposent pas leur logique interne. C'est facile à réaliser en raison de la façon dont ils sont conçus. Cependant, à moins que ce soit absolument nécessaire (par exemple, des événements d'envoi / diffusion), les abus d'utilisation des composants $scope
doivent être évités.
devraient assumer un seul rôle. Ceci est très important pour la testabilité, la réutilisabilité et la simplicité. Il est préférable de créer des composants supplémentaires au lieu de surcharger des composants individuels. Cela ne signifie pas que vous n'aurez pas de composants plus grands ou plus complexes, cela signifie simplement que chaque composant devrait se concentrer sur son travail principal.
Je divise les composants en quatre groupes principaux en fonction de leur rôle dans l'application pour vous aider à réfléchir à la façon de concevoir des composants. Il n'y a pas de syntaxe différente pour construire ces différents types de composants - considérez simplement les rôles spécifiques que les composants supposent.
ces types sont basés sur mes plus de 5 ans d'expérience en utilisant Angular. Vous pouvez choisir d'organiser légèrement différemment, mais le concept fondamental est de vous assurer que vos composants ont un rôle clair.
Un seul composant d'application peut agir comme racine de l'application. Vous pouvez le considérer comme ayant un seul composant dans le corps d'une application Web, à travers laquelle toutes les autres logiques sont chargées.
<code>> <app>></app>> > </code>
Ceci est principalement recommandé pour la cohérence de la conception angulaire 2, il sera donc plus facile à l'avenir si vous souhaitez migrer. Il aide également à tester en déplaçant tout le contenu racine de l'application dans un seul composant (plutôt qu'en mettant une partie dans le fichier index.html). Le composant d'application vous donne également un endroit pour instancier votre application afin que vous n'ayez pas à le faire dans la méthode d'exécution de l'application, ce qui améliore la testabilité et réduit la dépendance à $rootScope
.
Ce composant doit être aussi simple que possible. Si possible, il peut ne contenir que des modèles, sans liaisons ni contrôleurs. Cependant, il ne remplace pas ng-app
ou ne démarque pas les besoins d'application.
Dans le passé, nous avons lié des contrôleurs et des modèles à l'état d'interface utilisateur (ou routage NGROUTE). L'itinéraire peut désormais être lié directement au composant, donc le composant est toujours là où le contrôleur et la paire de modèles, mais il y a aussi les avantages d'être routables.
Par exemple, en utilisant l'interface utilisateur, c'est ainsi que nous lions les modèles et les contrôleurs.
<code>> <app>></app>> > </code>
Vous pouvez désormais relier l'URL directement au composant.
<code>$stateProvider.state('mystate', { url: '/', templateUrl: 'views/mystate.html', controller: MyStateController }); </code>
Ces composants peuvent lier les données des paramètres de routage tels que les ID de projet, et leur rôle est de se concentrer sur la configuration du routage pour charger les autres composants requis. Ce changement apparemment mineur vers la définition de routage est en fait très important pour les capacités de migration angular 2, mais elle est tout aussi importante dans Angular 1.5, car elle encapsule mieux les modèles et les contrôleurs au niveau des composants.
Angular 1 a en fait deux modules de routage, ngoute et ngComponentRouter. Seul NgComponentRouter prend en charge les composants, mais il est également obsolète. Je pense que la meilleure façon est d'utiliser l'interface utilisateur.
La plupart des seuls composants que vous créez pour votre application sont avec état. Ici, vous allez réellement placer la logique métier de l'application, émettre des demandes HTTP, des formulaires de processus et d'autres tâches avec état. Ces composants peuvent être uniques à votre application et se concentrent sur le maintien des données plutôt que sur le rendu visuel.
Supposons que vous ayez un contrôleur de chargement des données de profil utilisateur pour l'affichage, et qu'il existe également un modèle correspondant (non illustré ici) lié ensemble dans la directive. Cet extrait de code est probablement le contrôleur le plus élémentaire pour faire le travail.
<code>$stateProvider.state('mystate', { url: '/', component: 'mystate' }); </code>
En utilisant des composants, vous pouvez le concevoir mieux qu'avant. Idéalement, vous devez également utiliser le service au lieu d'utiliser $http
directement dans le contrôleur.
<code>.controller('ProfileCtrl', function ($scope, $http) { $http.get('/api/profile').then(function (data) { $scope.profile = data; }); }) .directive('profile', function() { return { templateUrl: 'views/profile.html', controller: 'ProfileCtrl' } }) </code>
Maintenant, vous avez un composant qui charge ses propres données, il devient donc avec état. Ces types de composants sont similaires aux composants de routage, sauf qu'ils peuvent ne pas être utilisés pour être liés à un seul itinéraire.
Le composant avec état utilisera d'autres composants (sans état) pour rendre réellement l'interface utilisateur. En outre, vous souhaitez toujours utiliser le service au lieu de mettre la logique d'accès aux données directement dans le contrôleur.
Les composants apatrides se concentrent sur le rendu sans gérer la logique métier et n'ont pas à être unique à une application particulière. Par exemple, la plupart des composants utilisés pour les éléments d'interface utilisateur tels que les contrôles de formulaire, les cartes, etc. ne gèrent pas non plus la logique comme le chargement des données ou les formulaires d'enregistrement. Ils sont conçus pour être très modulaires, réutilisables et isolés.
Si le composant sans état affiche uniquement des données ou tout dans le modèle de contrôle, un contrôleur peut ne pas être nécessaire. Ils accepteront la contribution des composants avec état. Cet exemple obtient la valeur du composant état (exemple de profil ci-dessus) et affiche l'avatar.
<code>.component('profile', { templateUrl: 'views/profile.html', controller: function($http) { var vm = this; // 当组件准备好时调用,见下文 vm.$onInit = function() { $http.get('/api/profile').then(function (data) { vm.profile = data; }); }; } }) </code>
Pour l'utiliser, le composant avec état passera le nom d'utilisateur via l'attribut, comme indiqué ci-dessous: <avatar username="vm.profile.username">.</avatar>
De nombreuses bibliothèques que vous utilisez sont des collections de composants sans état (et de services possibles). Ils peuvent certainement accepter des configurations pour modifier leur comportement, mais ils ne sont pas destinés à être responsables de la logique en dehors d'eux-mêmes.
Ce n'est pas nouveau dans le composant, mais il est généralement sage de l'utiliser dans le composant. Le but de la liaison à sens unique est d'éviter de charger plus de travail dans le cycle de digestion, ce qui est un facteur majeur des performances de l'application. Les données s'écoulent désormais dans le composant sans regarder à l'extérieur (ce qui conduit à certains problèmes de couplage qui existent aujourd'hui), et le composant peut simplement se rendre en fonction de cette entrée. Cette conception fonctionne également avec Angular 2, qui aide aux futures migrations.
Dans cet exemple, l'attribut de titre n'est lié au composant qu'une seule fois en fonction de la valeur initiale fournie. Si le titre est modifié par un acteur externe, il ne se reflétera pas dans le composant. La syntaxe qui indique que la liaison est unidirectionnelle est d'utiliser
<code>> <app>></app>> > </code>
Lorsque la propriété du titre change, le composant sera toujours mis à jour. Il est recommandé d'utiliser la liaison à sens unique dans la mesure du possible.
Angular a également la capacité de lier les données en un seul temps, vous pouvez donc optimiser le cycle de digestion. Essentiellement, Angular attendra pour fournir la première valeur non inhabituelle dans la liaison, lier cette valeur, puis (une fois que toutes les liaisons ont été analysées) supprimez l'observateur pertinent du cycle de digestion. Cela signifie qu'une liaison spécifique n'ajoute aucun temps de traitement à une future boucle de digest.
Cela se fait en précédant l'expression de liaison avec ::
. Si vous savez que la liaison d'entrée ne changera pas pendant le cycle de vie, il est logique de le faire. Dans cet exemple, si le titre est une liaison unidirectionnelle, il continuera à mettre à jour dans le composant, mais la liaison ici ne sera pas mise à jour car nous le spécifions comme une liaison à temps.
<code>$stateProvider.state('mystate', { url: '/', templateUrl: 'views/mystate.html', controller: MyStateController }); </code>
Vous avez peut-être remarqué la fonction $onInit
comme une nouvelle fonction. Les composants ont des cycles de vie et des événements correspondants que vous devez utiliser pour aider à gérer certains aspects du composant.
$onInit()
La première étape du cycle de vie des composants est l'initialisation. Cet événement s'exécute après l'initialisation du contrôleur et de la liaison. Vous devez presque toujours utiliser cette méthode pour la configuration ou l'initialisation des composants. Il garantira que toutes les valeurs sont disponibles pour le composant avant l'exécution. Si vous accédez aux valeurs liées directement dans le contrôleur, vous ne pouvez pas garantir que ces valeurs sont disponibles.
<code>$stateProvider.state('mystate', { url: '/', component: 'mystate' }); </code>
$postLink()
L'étape suivante consiste à relier tous les éléments enfants du modèle. Lorsque le composant est initialisé, rien ne garantit qu'il a également rendu des éléments enfants utilisés dans le modèle. Ceci est important si vous avez besoin d'exploiter le DOM de quelque manière que ce soit. Une mise en garde importante est que les modèles chargés de manière asynchrone n'ont peut-être pas été chargés lorsque l'événement est déclenché. Vous pouvez toujours utiliser une solution de mise en cache de modèle pour vous assurer que le modèle est toujours disponible.
<code>> <app>></app>> > </code>
$onChanges()
Lorsque le composant est actif, il peut avoir besoin de réagir aux changements des valeurs d'entrée. La liaison unidirectionnelle mettra à jour votre composant, mais nous avons une nouvelle liaison d'événements $onChanges
à écouter lorsque l'entrée change.
Pour cet exemple, supposons que le composant est fourni avec un titre et une description du produit. Vous pouvez détecter les modifications comme indiqué ci-dessous. Vous pouvez afficher l'objet transmis à la fonction, qui a des objets mappés aux liaisons disponibles, contenant la valeur actuelle et la valeur précédente.
<code>$stateProvider.state('mystate', { url: '/', templateUrl: 'views/mystate.html', controller: MyStateController }); </code>
$onDestroy()
L'étape finale consiste à supprimer les composants de la page. Cet événement se déroule avant que le contrôleur et sa portée ne soient détruits. Il est important de nettoyer tout ce que le composant peut créer ou maintenir de la mémoire, tels que les écouteurs d'événements, les observateurs ou d'autres éléments DOM.
<code>$stateProvider.state('mystate', { url: '/', component: 'mystate' }); </code>
Pour configurer et initialiser les composants avec un ensemble de données, les composants doivent utiliser les liaisons pour accepter ces valeurs. Ceci est parfois considéré comme une API composante, qui est juste une manière différente de décrire comment un composant accepte l'entrée.
Le défi ici est de fournir un nom concis mais clair pour la liaison. Parfois, les développeurs essaient de raccourcir le nom pour le rendre très concis, mais cela est dangereux pour l'utilisation de composants. Supposons que nous ayons un composant qui accepte le code stock en entrée, lequel des éléments suivants est le meilleur?
<code>.controller('ProfileCtrl', function ($scope, $http) { $http.get('/api/profile').then(function (data) { $scope.profile = data; }); }) .directive('profile', function() { return { templateUrl: 'views/profile.html', controller: 'ProfileCtrl' } }) </code>
J'espère que vous pensez que symbol
est meilleur. Parfois, les développeurs aiment également préfixer les composants et les liaisons comme un moyen d'éviter les conflits de noms. Il est sage de préfixer les composants, par exemple md-toolbar
est la barre d'outils de matériau, mais le préfixe pour toutes les liaisons peut devenir verbeux et doit être évité.
Afin de communiquer avec d'autres composants, le composant doit publier un événement personnalisé. Il existe de nombreux exemples d'utilisation de services et de liaison de données bidirectionnelle pour synchroniser le nombre entre les composants
c'est le cas, mais les événements sont un meilleur choix de conception. Les événements sont beaucoup plus efficaces comme moyen de communiquer avec les pages (et sont la partie fondamentale de la langue JavaScript et comment cela fonctionne dans Angular 2, pas de coïncidence).
Les événements dans peuvent être utilisés avec $emit
(jusqu'à la portée de l'arbre) ou $broadcast
(jusqu'à Scope Tree). Ceci est une application pratique d'un exemple rapide.
<code>.component('profile', { templateUrl: 'views/profile.html', controller: function($http) { var vm = this; // 当组件准备好时调用,见下文 vm.$onInit = function() { $http.get('/api/profile').then(function (data) { vm.profile = data; }); }; } }) </code>
Il existe deux situations principales dans lesquelles vous devez communiquer entre les composants: entre les composants que vous connaissez et entre les composants que vous ne connaissez pas. Pour illustrer cette différence, supposons que nous avons un ensemble de composants pour aider à gérer les onglets sur la page et une barre d'outils avec des liens de page d'aide correspondants.
<code>.component('avatar', { template: '<img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173975605585460.png" class="lazy" ng- alt="Un guide pour construire des composants angulaires de qualité 1,5" >', bindings: { username: ' }, controllerAs: 'vm' }) </code>
Dans ce cas, les composants my-tabs
et my-tab
peuvent se connaître car ils travaillent ensemble pour créer un ensemble de trois onglets différents. Cependant, les composants my-toolbar
sont au-delà de leur portée cognitive.
Chaque fois qu'un onglet différent est sélectionné (ce sera un événement sur l'instance de composante my-tab
), le composant my-tabs
doit savoir afin qu'il puisse ajuster l'affichage de l'onglet pour afficher l'instance. Le composant my-tab
peut émettre des événements vers le haut vers le composant parent my-tabs
. Ce type de communication est comme une communication interne entre deux composants qui fonctionnent ensemble pour créer une seule fonction (une interface à onglets).
Mais que se passe-t-il si my-toolbar
Vous voulez savoir quel onglet est actuellement sélectionné afin qu'il puisse modifier le bouton d'aide en fonction du contenu visible? L'événement my-tab
n'atteindra jamais my-toolbar
car ce n'est pas un parent. Ainsi, une autre option consiste à utiliser $rootScope
pour émettre des événements pour l'ensemble de l'arborescence des composants, ce qui permet à tout composant d'écouter et de réagir. L'inconvénient potentiel ici est que vos événements atteignent désormais chaque contrôleur, et si un autre composant utilise le même nom d'événement, vous pouvez déclencher des effets inattendus.
Déterminez quelle approche convient à votre cas d'utilisation, mais chaque fois qu'un autre composant peut avoir besoin de connaître l'événement, vous voudrez peut-être émettre des événements à l'ensemble de l'arborescence des composants en utilisant la deuxième option.
Les applications Angular 1 peuvent désormais être écrites à l'aide de composants, ce qui modifie les meilleures pratiques et la meilleure nature de la rédaction de notre application. C'est pour le meilleur, mais utiliser le simple fait d'utiliser des composants n'est pas nécessairement meilleur qu'auparavant. Gardez les points suivants à l'esprit lors de la construction de composants angulaires 1.
$onChanges
pour observer les changements. utilisez-vous des composants dans votre application angulaire 1.x? Ou, allez-vous attendre de passer à Angular 2? J'adorerais entendre parler de votre expérience dans les commentaires ci-dessous.
Le composant Angular 1.5 est une API plus simple et plus intuitive pour créer des directives. Bien que les instructions soient puissantes, ils peuvent être difficiles à utiliser en raison de leur flexibilité. D'un autre côté, les composants ont des configurations plus simples et sont conçus pour être utilisés pour construire des éléments d'interface utilisateur. Ils facilitent également l'utilisation de liaisons de données unidirectionnelles et de crochets de cycle de vie, ce qui peut conduire à un flux de données plus prévisible et à un débogage plus facile.
La liaison des données unidirectionnelle peut être obtenue en utilisant l'attribut bindings
dans le composant angulaire 1.5.
Le cycle de vie est une fonction appelée point spécifique du cycle de vie d'un composant. Angular 1.5 introduit plusieurs crochets de cycle de vie, tels que $onInit
, $onChanges
, $onDestroy
et $postLink
. Ces crochets peuvent être utilisés pour effectuer des tâches telles que l'initialisation des données, le nettoyage des ressources ou la réaction des modifications de liaison.
La communication entre les composants peut être obtenue en utilisant des liaisons et des événements dans Angular 1.5. La communication parent-fils peut être effectuée en utilisant la liaison, tandis que la communication d'enfant à parent peut être effectuée à l'aide d'événements. Cela facilite le flux de données unidirectionnel, ce qui peut rendre votre application plus facile à comprendre.
Migrer des directives de 1,5 angulaire aux composants implique plusieurs étapes. Tout d'abord, remplacez la directive pour définir l'objet par la définition des composants. Ensuite, remplacez la fonction de liaison par le crochet du cycle de vie. Enfin, remplacez la liaison des données bidirectionnelle par la liaison et les événements de données unidirectionnels.
Les composants de 1,5 angulaire offrent plusieurs avantages sur les instructions. Ils ont une API plus simple qui facilite la liaison des données unidirectionnelle et le flux de données unidirectionnel, et fournit des crochets de cycle de vie. Ces fonctionnalités peuvent rendre votre code plus facile à comprendre, à déboguer et à maintenir.
peut être obtenue dans des composants angulaires 1.5 en utilisant l'option transclude
dans la définition des composants. Cela vous permet d'insérer du contenu personnalisé dans le modèle du composant, ce qui est très utile pour créer des éléments d'interface utilisateur réutilisables.
La transcription multi-emplacement peut être implémentée dans des composants angulaires 1.5 en utilisant l'option transclude
avec la syntaxe d'objet. Cela vous permet de définir plusieurs emplacements de transcription dans le modèle du composant qui peuvent être remplis de contenu personnalisé.
$onChanges
Hook de cycle de vie dans le composant Angular 1.5? Chaque fois qu'une liaison unidirectionnelle est mise à jour, le crochet de cycle de vie $onChanges
dans le composant angulaire 1.5 est appelé. Il reçoit un objet de changement contenant les valeurs actuelles et précédentes de la liaison. Cela peut être utilisé pour réagir aux modifications de liaison et effectuer des tâches telles que la mise à jour de l'état des composants ou l'obtention de données.
$postLink
Hook de cycle de vie dans le composant Angular 1.5? Une fois que l'élément du composant et ses éléments enfants sont liés, le crochet de cycle de vie $postLink
dans le composant angulaire 1.5 sera appelé. Cela peut être utilisé pour effectuer des tâches qui nécessitent un accès aux éléments DOM du composant, tels que la configuration d'un écouteur d'événements ou l'exploitation du DOM.
Ce 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!