web-dev-qa-db-fra.com

Angular 2 + / 4/5/6/7: communication de composants intelligente, stupide et profondément imbriquée

REMARQUE: pour plus de simplicité, considérez les profondeurs des composants comme:

- Smart (grand)parent level 0
  - dumb child level 1
   ....
    - dumb grandchild level 2
      ....)

Il existe différentes options et conditions sur la façon dont les composants intelligents/grand/parent/enfant communiquent et transmettent les données de haut en bas d'une chaîne MULTI-NIVEAUX (au moins 3 niveaux). Nous aimerions garder notre composant parent (intelligent) (grand) comme le seul composant qui ait accès à notre service de données (ou magasin atomique/immuable) et cela conduira à l'échange d'informations avec les (petits) enfants `` stupides ''. Les options que nous voyons sont:

  1. Anti-motif (?): Transmettre des données de haut en bas de la chaîne de composants via les liaisons @ Input/@ Output. C'est ce que certains appellent le problème des "propriétés étrangères" ou du "problème de propagation d'événement personnalisé" (par exemple: ici et ici .)). Ne pas aller.
  2. Anti-modèle: accès intelligent aux composants pour les (petits) enfants stupides via @ViewChildren ou @ContentChilden. Cela a de nouveau câblé les enfants et ne crée toujours pas un mécanisme propre pour les (grands) enfants pour transmettre des données au composant intelligent.
  3. Service de messagerie partagé comme décrit dans le livre de recettes angular.io ici et un excellent article ici .
  4. ?

Maintenant, en cas de "3", les (petits) enfants muets doivent recevoir le service de messagerie. Ce qui m'amène à mes questions:

Q1: Il semble intuitivement étrange que chacun des (petits) enfants "muets" se fasse injecter un service de messagerie. La meilleure pratique est-elle que le service de messagerie soit un service dédié à cette famille OR est-ce qu'il se superpose au service de données dont le grand-parent "intelligent" est chargé ci-dessus?

Q1A: De plus, en quoi est-ce bien mieux que d'ajouter des liaisons @ Input/@ Output dans la chaîne si tous les composants auront un service injecté? (Je vois l'argument selon lequel le composant "stupide" a besoin de QUELQUE manière pour obtenir des informations)

Q2: Et si le grand parent "intelligent" communiquait avec un magasin de type redux (ngrx pour nous)? Encore une fois, la communication avec les composants "stupides" se fait-elle le mieux via un service de messages injectés/dédiés ou est-il préférable d'injecter le magasin dans chaque composant "stupide" ... ou? Remarque, la communication inter-composants est une combinaison `` d'actions '' (par exemple: validation de formulaire, bouton de désactivation, etc.) en plus des données (c'est-à-dire ajouter des données à/mettre à jour le magasin ou le service).

Réflexions grandement appréciées!

24
MoMo

(MISE À JOUR: 02-07-2019: Ce message était en train de devenir daté - a ajouté le modèle 'store/ngrx')

Donc, après avoir approfondi cette question, en ce qui concerne la meilleure façon de communiquer de haut en bas sur une chaîne de composants imbriqués, il ne semble y avoir vraiment que deux options - une négociation faustienne entre:

SOIT

  • soit passer les liaisons @ Input/@ Output vers le haut, vers le bas et tout au long de la chaîne de composants imbriqués (c'est-à-dire gérer les problèmes de `` propagation d'événement personnalisé '' ou de `` propriétés étrangères '')

OR

  • Utilisez un service de messagerie/abonnement pour communiquer entre cette famille de composants (grande description ici ) et injectez ce service pour chaque composant de la chaîne.

OU:

  • Le modèle de stockage réactif (par exemple, 'ngrx') est une autre option. Notez, OMI, que les notions de composants intelligents et stupides s'appliquent toujours. À savoir, les composants stupides n'accèdent jamais directement au magasin. Encore une fois, les composants intelligents sont la partie principale pour obtenir des données via le magasin.

Je suis personnellement un partisan de l'utilisation de composants intelligents et de présentation ("stupides"). L'ajout d'un `` magasin '' doit également être effectué de manière sélective car il augmente considérablement les coûts du processus, allant de l'architecture, des modèles de mise en œuvre cohérents, du développement et de la maintenance à l'intégration de nouveaux membres du personnel. En théorie, un composant "stupide" n'a besoin que de @Inputs et @Outputs et c'est tout. Peu importe sa profondeur ou sa profondeur dans une arborescence de composants - c'est le problème des applications. En fait, peu importe l'application qui l'utilise en premier lieu. Pendant ce temps, un composant en profondeur n'est pas très stupide ou transportable si un service spécifique à l'application y est injecté. BTW, le composant `` intelligent '' de contrepartie fournit vraiment des services intermédiaires (via un service @Injectable de première classe ou un magasin de type redux) à tout composant stupide de son arbre généalogique qui en a besoin. Le composant intelligent ne se soucie pas non plus des composants au-delà des @Inputs de son enfant immédiat tant que les petits-enfants signalent d'une manière ou d'une autre qu'une action de service/magasin doit être entreprise (à nouveau via la chaîne @ Input/@ Output). De cette façon, un composant intelligent devient également transportable à travers les lignes d'application.

Compte tenu de cela, le marché faustien, l'OMI, penche pour l'utilisation d'une chaîne @ Input/@ Output avec tous les problèmes mentionnés qu'elle entraîne. Cela dit, je garde un œil sur cela et je me réjouis des alternatives propres et découplées si quelqu'un en connaît.

10
MoMo

Pourquoi # 1 est-il un anti-modèle? Le composant grand-parent possède les données et les transmet aux composants enfants muets via les paramètres @Input. Les composants enfants stupides appellent simplement des rappels lorsqu'un événement se produit (via les émetteurs d'événements @Output), ce qui oblige le composant grand-parent à manipuler les données. Ça me semble propre.

Edit: Je vois votre point sur le passage répétitif de valeurs comme un gestionnaire de soumission à travers de nombreuses couches intermédiaires. Peut-être qu'une structure imbriquée qui représente votre arborescence de composants pourrait être créée dans le composant parent. Ensuite, chaque composant peut recevoir les propriétés dont il a besoin, plus un objet à transmettre au composant suivant. Chaque composant ne connaît alors que celui en dessous:

// Parent component builds this object (or gets a service to do it)

viewModelForChildComponent: {

    property1NeededForChildComponent,

    property2NeededForChildComponent,

    viewModelForGrandChildComponent: {
        property1NeededForGrandChildComponent,

        property2NeededForGrandChildComponent,

        viewModelForGrandGrandChildComponent: {
            property1NeededForGrandGrandChildComponent,

            submitHandlerNeededForGrandGrandChildComponent
        }
    }
}
1
Frank Modica

Les liaisons Input () et Output () sont également un moyen parfaitement légitime de gérer cela. Laissez le composant intelligent gérer la logique de génération des valeurs, puis utilisez Input () et Output () pour simplement transmettre et recevoir les valeurs le long de la chaîne de composants.

Bien sûr, cela indique l'un des inconvénients de l'approche smart/view: plus de fichiers; plus de passe-partout. C'est pourquoi je ne plaiderais pas pour une approche unique qui soit universelle. Choisissez plutôt une approche qui a du sens dans votre contexte actuel (à la fois pour l'application et pour votre organisation).

1
Muirik