Maison  >  Article  >  interface Web  >  Compréhension approfondie du modèle d'injection de dépendances dans Angular (play case)

Compréhension approfondie du modèle d'injection de dépendances dans Angular (play case)

青灯夜游
青灯夜游avant
2022-06-24 15:28:432604parcourir

Cet article vous donnera une compréhension approfondie du mode d'injection de dépendances dans Angular et partagera des cas d'application et de gameplay du mode d'injection de dépendances. J'espère qu'il sera utile à tout le monde !

Compréhension approfondie du modèle d'injection de dépendances dans Angular (play case)

1 Injection, un mode de communication et un modèle de conception au niveau de l'arborescence des composants

1.1 Mode de communication des composants

Dans le développement de l'ingénierie angulaire, nous utilisons généralement la liaison de propriété d'entrée et la liaison d'événement de sortie Communication de composant, cependant Entrée et Output ne peut transmettre des informations qu'entre les composants parent et enfant. Les composants forment une arborescence de composants basée sur la relation d'appel. S'il n'y a que des liaisons de propriétés et des liaisons d'événements, alors deux composants de relation non directe doivent communiquer via chaque point de connexion lui-même. L'intermédiaire doit continuellement traiter et transmettre certaines choses qu'il fait. pas besoin de connaître les informations (Figure 1 à gauche). Le service injectable fourni dans Angular peut être fourni sous forme de modules, de composants ou d'instructions, et combiné à l'injection dans le constructeur, peut résoudre ce problème (à droite sur la figure 1). [Recommandation de tutoriel connexe : "Tutoriel angulaire"]

Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

Figure 1 Mode de communication des composants

L'image de gauche transmet uniquement les informations via les composants parent-enfant. Le nœud a et le nœud b doivent passer par de nombreux nœuds pour communiquer ; si le nœud c veut contrôler le nœud b via une certaine configuration, les nœuds entre eux doivent également définir des attributs ou des événements supplémentaires pour transmettre de manière transparente les informations correspondantes. Dans le mode d'injection de dépendances à droite, le nœud c peut fournir un service permettant aux nœuds a et b de communiquer. Le nœud a communique directement avec le service fourni par le nœud c, et le nœud b communique également directement avec le service fourni par le nœud c. , la communication est simplifiée et le nœud du milieu n'est pas couplé à cette partie du contenu et n'a aucune conscience évidente de la communication qui se produit entre les composants supérieurs et inférieurs.

1.2 Utilisation de l'injection de dépendances pour implémenter l'inversion de contrôle

L'injection de dépendances (DI) n'est pas unique à Angular. C'est un moyen d'implémenter le modèle de conception d'inversion de contrôle (IOC). L'émergence de l'injection de dépendances résout le problème. de surcouplage de l'instanciation manuelle. Le problème est que toutes les ressources ne sont pas gérées par les deux parties utilisant les ressources, mais fournies par le centre de ressources ou un tiers, ce qui peut apporter de nombreux avantages. Premièrement, la gestion centralisée des ressources rend les ressources configurables et faciles à gérer. Deuxièmement, cela réduit le degré de dépendance entre les deux parties utilisant les ressources, ce que nous appelons le couplage.

Une analogie avec le monde réel est que lorsque nous achetons un produit tel qu'un crayon, il nous suffit de trouver un magasin pour acheter un produit de ce type. Peu importe où le crayon est produit ou comment le bois et le bois sont utilisés. Les mines de crayon sont liées. Oui, nous en avons juste besoin pour compléter la fonction d'écriture d'un crayon. Nous n'aurons aucun contact avec le fabricant ou l'usine de crayon spécifique. Quant au magasin, il peut acheter des crayons auprès des canaux appropriés et réaliser la configurabilité des ressources.

Combiné avec des scénarios de codage, plus précisément, les utilisateurs n'ont pas besoin de créer explicitement des instances (nouvelles opérations) pour injecter et utiliser des instances. La création d'instances est déterminée par les fournisseurs. La gestion des ressources se fait via des jetons. Puisqu'il ne se soucie pas du fournisseur ou de la création d'instances, l'utilisateur peut utiliser certaines méthodes d'injection locales (configuration secondaire des jetons) pour enfin réaliser le remplacement d'instance et le mode d'injection de dépendances. Applications et programmation d'aspect (AOP). ) se complètent.

2 Injection de dépendances dans Angular

L'injection de dépendances est l'un des modules de base les plus importants du framework Angular. Angular fournit non seulement une injection de type de service, mais l'arborescence des composants elle-même est une arborescence de dépendances d'injection. peut également être utilisé a été injecté. C'est-à-dire que dans le framework Angular, les composants enfants peuvent injecter des instances de composant parent via le jeton du composant parent (généralement le nom de la classe). Dans le développement d'une bibliothèque de composants, il existe un grand nombre de cas où l'interaction et la communication sont obtenues en injectant des composants parents, y compris le montage de paramètres, le partage d'état et même l'obtention du DOM du nœud où se trouve le composant parent, etc.

2.1 Résolution des dépendances

Pour utiliser l'injection angulaire, vous devez d'abord comprendre son processus de résolution d'injection. Semblable au processus d'analyse de node_modules, lorsqu'aucune dépendance n'est trouvée, les dépendances remonteront toujours jusqu'à la couche parent pour trouver les dépendances. L'ancienne version d'Angular (avant v6) divise le processus d'analyse d'injection en injecteurs de modules multi-niveaux, injecteurs de composants multi-niveaux et injecteurs d'éléments. La nouvelle version (après v9) est simplifiée en un modèle à deux niveaux. La première chaîne de requêtes est l'injecteur d'éléments statiques au niveau DOM, l'injecteur de composants, etc., collectivement appelés injecteurs d'éléments, et l'autre chaîne de requêtes est l'injecteur de module. . L'ordre d'analyse et la valeur par défaut après l'échec de l'analyse sont expliqués plus clairement dans le document de commentaire du code officiel (provider_flag).

Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

Figure 2 Le processus de recherche de dépendances de l'injecteur à deux niveaux (Source de l'image)

C'est-à-dire que les composants/instructions et la fourniture de contenu injecté au niveau composant/instruction rechercheront d'abord les dépendances dans les éléments dans la vue des composants jusqu'à l'élément racine, s'il n'est pas trouvé, recherchez le module parent du module jusqu'à ce que le module racine et le module de plateforme soient référencés (y compris les références de module et les références de chargement différé de routage) dans le module où se trouve l'élément actuellement situé.

Notez que l'injecteur ici a un héritage. L'injecteur d'élément peut créer et hériter de la fonction de recherche de l'injecteur de l'élément parent, et l'injecteur de module est similaire. Après un héritage continu, cela devient un peu comme la chaîne prototype d'objets js.

2.2 Fournisseur de configuration

Comprenant la priorité d'ordre de résolution des dépendances, nous pouvons fournir du contenu au niveau approprié. On sait déjà qu'il en existe deux types : l'injection de modules et l'injection d'éléments.

  • Injecteur de module : les fournisseurs peuvent être configurés dans l'attribut de métadonnées de @NgModule, et vous pouvez également utiliser l'instruction @Injectable fournie après la v6. L'instruction provideIn est le nom du module, 'root', etc. (En fait, il y a deux injecteurs au-dessus du module racine, Platform et Null. Ils ne seront pas abordés ici.)

  • Injecteur d'élément : fournisseurs, viewProviders ou fournisseurs.

dans les métadonnées @Directive de la directive. De plus, en fait, en plus d'utiliser le décorateur @Injectable pour déclarer un injecteur de module, il peut également être déclaré comme injecteur d'élément. Le plus souvent il sera déclaré comme fourni à la racine pour implémenter un singleton. Il intègre les métadonnées via la classe elle-même pour éviter que les modules ou composants déclarent directement et explicitement le fournisseur. De cette façon, si la classe n'a pas de service de directive de composant et d'autres classes pour l'injecter, il n'y aura pas de code lié à la déclaration de type et. il peut être ignoré par le compilateur, réalisant ainsi Secouer l'arbre.

Une autre façon de le fournir est de donner directement la valeur lors de la déclaration d'InjectionToken.

Voici les modèles abrégés pour ces méthodes :

@NgModule({  providers: [
    // 模块注入器
  ]
})
export class MyModule {}
@Component({  providers: [
    // 元素注入器 - 组件
  ],  
  viewProviders: [
      // 元素注入器- 组件视图
  ]
})
export class MyComponent {}
@Directive({  providers: [
   // 元素注入器 - 指令
 ]
})
export class MyDirective {}
@Injectable({
 providedIn: 'root'
})
export class MyService {}
export const MY_INJECT_TOKEN = new InjectionToken<myclass>('my-inject-token', {
 providedIn: 'root',
 factory: () => {
    return new MyClass();
 }
});</myclass>

Différentes options pour fournir des emplacements de dépendances apporteront certaines différences, qui affectent en fin de compte la taille du package, la portée des dépendances qui peuvent être injectées et le cycle de vie des dépendances. Il existe différentes solutions applicables pour différents scénarios, tels que singleton (racine), isolation de service (module), fenêtres d'édition multiples (composant), etc. Vous devez choisir un emplacement raisonnable pour éviter les informations partagées inappropriées ou le packaging de code redondant.

2.3 Divers outils de fonction de valeur

Si vous fournissez uniquement l'injection d'instance, cela ne montrera pas la flexibilité de l'injection de dépendances du framework Angular. Angular fournit de nombreux outils d'injection flexibles. useClass crée automatiquement de nouvelles instances, useValue utilise des valeurs statiques, useExisting peut réutiliser des instances existantes et useFactory est construit via des fonctions, avec des dépôts spécifiés et des paramètres de constructeur spécifiés. Vous pouvez couper le jeton d'une classe et le remplacer par une autre instance que vous avez préparée. Vous pouvez d'abord créer un jeton pour enregistrer la valeur ou l'instance, puis le remplacer à nouveau lorsque vous en aurez besoin plus tard. la fonction d'usine pour la renvoyer. Les informations locales de l'instance sont mappées à une autre valeur d'objet ou d'attribut. Le gameplay ici sera expliqué à travers des cas ultérieurs, je ne m’étendrai donc pas ici. Le site officiel propose également de nombreux exemples de référence.

2.4 Consommation d'injection et décorateur

L'injection dans Angular peut être injectée dans le constructeur, ou vous pouvez demander à l'injecteur d'obtenir les éléments injectés existants via la méthode get.

Angular prend en charge l'ajout de décorateurs à marquer lors de l'injection,

  • @Host() pour limiter le bouillonnement
  • @Self() à l'élément lui-même
  • @SkipSelf() pour le limiter à l'élément lui-même
  • @Optional () Marqué comme facultatif
  • @Inject() limité aux jetons de jetons personnalisés

Voici un article "@Self ou @Optional @Host ? Le guide visuel des décorateurs Angular DI." Montre très clairement les différences dans les instances qui sera touché si différents décorateurs sont utilisés entre les composants parent et enfant.

Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

Figure 3 Résultats de filtrage des différents décorateurs injectés

2.4.1 Supplément : Parmi la vue hôte et @Host

, le plus difficile à comprendre est probablement @Host, voici un supplément Quelques spécifiques à @Host instructions. L'explication officielle du décorateur @Host est

... récupérer une dépendance de n'importe quel injecteur jusqu'à atteindre l'élément hôte

Host signifie ici hôte. Le décorateur @Host limitera la portée de la requête à l'élément hôte. Qu'est-ce qu'un élément hôte ? Si le composant B est un composant utilisé par le modèle du composant A, alors l'instance du composant A est l'élément hôte de l'instance du composant B. Le contenu généré par le modèle de composant est appelé une vue. La même vue peut comporter différentes vues pour différents composants. Si le composant A utilise le composant B dans sa propre portée de modèle (voir Figure 4), la vue (partie du cadre rouge) formée par le contenu du modèle de A est la vue intégrée du composant A, et le composant B se trouve dans cette vue, donc pour B , cette vue est la vue hôte de B. Le décorateur @Host limite la portée de la recherche à la vue hôte. Si elle n'est pas trouvée, elle ne bouillonnera pas.

Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

Figure 4 Vue en ligne et vue hôte

3 Cas et gameplay

Prenons un cas réel pour voir comment fonctionne l'injection de dépendances, comment résoudre les erreurs et quoi d'autre peut être fait en jouant.

3.1 Cas 1 : La fenêtre modale crée un composant dynamique, mais le composant est introuvable

Le composant de fenêtre modale de la bibliothèque de composants DevUI fournit un service ModalService, qui peut faire apparaître une boîte modale et peut être configuré pour composants définis automatiquement. Les étudiants en commerce signalent souvent des erreurs lors de l'utilisation de ce composant, indiquant que le package ne parvient pas à trouver le composant personnalisé.

Par exemple, le rapport d'erreur suivant :

Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

Figure 5 Lors de l'utilisation de ModalService, le rapport d'erreur lors de la création d'un composant faisant référence à EditorX ne trouve pas le fournisseur de services correspondant

Analysez comment ModalService crée des composants personnalisés, Code source de ModalService Fonction ouverte Ligne 52 et ligne 95. Comme vous pouvez le voir, si componentFactoryResolver n'est pas transmis, le componentFactoryResolver injecté par ModalService sera utilisé. Dans la plupart des cas, l'entreprise introduira DevUIModule une fois dans le module racine, mais n'introduira pas ModalModule dans le module actuel. Autrement dit, la situation actuelle de la figure 6 est la suivante. Selon la figure 6, il n'y a pas de EditorXModuleService dans l'injecteur de ModalService. componentFactoryResolver如果没有传入就使用ModalService注入的componentFactoryResolver。而大多数情况下,业务会在根模块引入一次DevUIModule,但是不会在当前模块里引入ModalModule。也就是现状图6是这样的。根据图6,ModalService的injector内是没有EditorXModuleService的。

Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

图6 模块服务提供关系图

根据注入器的继承,解决办法有四个:

  • 把 EditorXModule 放到 ModalModule 声明的地方,这样注入器就能找到EditorXModule提供的EditorModuleService —— 这是最糟糕的一种解法,本身loadChildren实现的懒加载就是为了减少首页模块的加载,结果是子页内需要用到的内容却放在AppModule,首次加载就把富文本的大模块给加载了,加重了FMP(First Meaningful Paint),不可采取。

  • 在引入 EditorXModule 且使用 ModalService 的模块里引入 ModalService —— 可取。仅有一种情况不太可取,就是调用 ModalService 的是另一个靠顶层的公共 Service,这样还是把不必要的模块放在了上层去加载。

  • 在触发使用ModalService的组件,注入当前模块的componentFactoryResolver,并传给ModalService的open函数参数 —— 可取, 可以在真正使用的地方再引入EditorXModule。

  • 在使用的模块里,手动提供一个ModalService —— 可取,解决了注入搜索的问题。

四种方法其实都是在解决 ModalService 所用的componentFactoryResolver

Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

Photo 6 Diagramme de relation de prestation de service du module

Selon l'héritage de l'injecteur, il existe quatre solutions :

  • Placez le EditorXModule là où le ModalModule est déclaré, comme ça L'injecteur peut trouver le EditorModuleService fourni par EditorXModule - c'est la pire solution. Le chargement paresseux implémenté par loadChildren lui-même consiste à réduire le chargement du module de page d'accueil. Le résultat est que le contenu qui doit être utilisé dans la sous-page est. placé dans l'AppModule Pour la première fois, le chargement chargera le gros module de texte riche, ce qui augmentera le FMP (First Meaningful Paint) et ne pourra pas être adopté.

Introduisez ModalService dans le module qui introduit EditorXModule et utilise ModalService - conseillé. Il n'y a qu'une seule situation qui n'est pas recommandée, c'est que l'appel de ModalService est un autre service public de niveau supérieur, qui place toujours les modules inutiles sur la couche supérieure pour le chargement.

  • Lors du déclenchement du composant qui utilise ModalService, injectez le componentFactoryResolver du module actuel et transmettez-le au paramètre de fonction open de ModalService - conseillé, vous pouvez introduire EditorXModule là où il est effectivement utilisé.

  • Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)Dans le module utilisé, il est conseillé de fournir manuellement un ModalService, ce qui résout le problème de l'injection de recherche.
  • Les quatre méthodes résolvent en fait le problème de EditorXModuleService dans la chaîne interne de l'injecteur de componentFactoryResolver utilisé par ModalService. En garantissant que la chaîne de recherche se situe à deux niveaux, ce problème peut être résolu. Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Résumé des points de connaissance

     : Héritage des injecteurs de modules et portée de recherche. 🎜🎜🎜3.2 Cas 2 : CdkVirtualScrollFor ne trouve pas CdkVirtualScrollViewport🎜🎜🎜Habituellement, lorsque nous utilisons le même modèle à plusieurs endroits, nous extrayons les parties communes via le modèle. Lors du développement du composant DevUI Select auparavant, le développeur souhaitait extraire les parties communes. . Une erreur a été signalée. 🎜🎜🎜🎜🎜🎜🎜🎜Figure 7 Erreur de mouvement et d'injection de code introuvable🎜

    Cela est dû au fait que l'instruction CdkVirtualScrollFor doit injecter un CdkVirtualScrollViewport. Cependant, le système d'héritage de l'injecteur d'injection d'éléments hérite du DOM de la relation AST statique, et la relation dynamique ne fonctionne pas. Par conséquent, le comportement de requête suivant se produit et la recherche échoue. .

    Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 8 Plage de recherche de la chaîne de requête de l'injecteur d'élément

    Solution finale : soit 1) Gardez la position du code d'origine inchangée, soit 2) Vous devez intégrer l'intégralité du modèle pour le trouver.

    Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 9 L'ensemble du module intégré permet à CdkVitualScrollFo de trouver CdkVirtualScrollViewport (Solution 2)

    Résumé des points de connaissance : La chaîne de requête de l'injecteur d'éléments est l'ancêtre de l'élément DOM du modèle statique.

    3.3 Cas 3 : Le composant de vérification du formulaire est encapsulé dans un sous-composant et ne peut pas être vérifié

    Ce cas provient de ce blog "Angular : Formulaire piloté par un modèle imbriqué".

    Nous avons également rencontré le même problème lors de l'utilisation de la validation de formulaire. Comme le montre la figure 10, pour certaines raisons, nous encapsulons les adresses des trois champs dans un composant pour les réutiliser.

    1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 10 Encapsuler les trois champs d'adresse du formulaire dans un sous-composant

    À ce moment, nous trouverons une erreur, ngModelGroup a besoin d'un ControlContainer à l'intérieur le host , qui est le contenu fourni par la directive ngForm. ngModelGroup需要一个host内部的ControlContainer,也就是ngForm指令提供的内容。

    1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    图11 ngModelGroup 找不到ControlContainer

    查看ngModelGroup代码可以看到它只添加了host装饰器的限制。

    1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    图12 ng_model_group.ts限定了注入ControlContainer的范围

    这里可以使用viewProvider搭配usingExisting给AddressComponent的宿主视图增加ControlContainer的Provider

    1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    图13 使用viewProviders给嵌套组件提供外部的Provider

    知识点小结:viewProvider 和 usingExisting 搭配的妙用。

    3.4 案例四:拖拽模块提供的Service,由于懒加载,不是单例了,导致无法互相拖拽

    内部的业务平台有涉及跨多个模块的拖拽,由于涉及了loadChildren懒加载,每个模块会单独打包DevUI组件库的DragDropModule,该Module提供了一个DragDropService。拖拽指令分为可拖起指令Draggable和可放置指令Droppable,两个指令通过DragDropService进行通信。 本来引入同一个模块使用模块提供的Service是可以通信的,但是懒加载后DragDropModule模块被打包了两次,也对应产生两份隔离的实例。这时候处于一个懒加载模块里的Draggable指令就无法与另一个懒加载模块里的Droppable指令进行通信了,因为此时DragDropService并不是同个实例了。

    1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    图14 懒加载模块导致服务不是同一实例/单例

    这里明显我们的述求是需要单例,而单例的做法通常就是providerIn: 'root'

    1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Photo 11 ngModelGroup ne trouve pas ControlContainer

    1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)En regardant le code de ngModelGroup, vous pouvez voir qu'il ajoute uniquement la restriction du décorateur hôte.

    1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Photo 12 ng_model_group.ts limite la portée de l'injection de ControlContainer1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Ici, vous pouvez utiliser viewProvider avec usingExisting pour ajouter le fournisseur de ControlContainer à la vue hôte de AddressComponent

    1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    🎜Figure 13 Utilisez viewProviders pour fournir des fournisseurs externes aux composants imbriqués🎜🎜🎜Résumé des points de connaissance🎜 : Combinaison de viewProvider et usingExisting Une utilisation merveilleuse. 🎜

    🎜3.4 Cas 4 : Le service fourni par le module glisser-déposer n'est plus un singleton en raison d'un chargement paresseux, ce qui entraîne l'impossibilité de glisser-déposer les uns les autres🎜🎜🎜 La plate-forme métier interne implique plusieurs Pour le déplacement de modules, en raison du chargement paresseux de loadChildren, chaque module emballera séparément le DragDropModule de la bibliothèque de composants DevUI, qui fournit un DragDropService. Les instructions glisser-déposer sont divisées en instructions Draggable et Droppable. Les deux instructions communiquent via DragDropService. À l'origine, il était possible de communiquer en introduisant le même module et en utilisant le service fourni par le module. Cependant, après un chargement paresseux, le module DragDropModule a été empaqueté deux fois, ce qui a également abouti à deux instances isolées. À l'heure actuelle, l'instruction Draggable dans un module chargé paresseusement ne peut pas communiquer avec l'instruction Droppable dans un autre module chargé paresseusement, car DragDropService n'est pas la même instance à ce moment. 🎜🎜1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)🎜🎜Photo 14 Le chargement paresseux des modules conduit à ce que les services ne soient pas la même instance/cas unique🎜🎜Il est évident que notre exigence ici est que nous avons besoin d'un singleton, et la méthode singleton est généralement providerIn: 'root' , alors il est préférable de laisser le DragDropService de la bibliothèque de composants ne pas être fourni au niveau du module, mais directement fourni dans le domaine racine ? Mais si l’on y réfléchit bien, il y a d’autres problèmes ici. La bibliothèque de composants elle-même est destinée à être utilisée par diverses entreprises. Si certaines entreprises disposent de deux groupes glisser-déposer correspondants à deux endroits de la page, elles ne souhaitent pas être liées. A cette époque, le singleton détruit cet isolement naturel basé sur les modules. 🎜🎜Il serait alors plus raisonnable de mettre en œuvre le remplacement des singletons du côté commercial. Rappelez-vous la chaîne de requête de dépendance que nous avons mentionnée plus tôt. L'injecteur d'élément est recherché en premier. S'il n'est pas trouvé, l'injecteur de module est démarré. L’idée de remplacement est donc que nous pouvons fournir des fournisseurs au niveau des éléments. 🎜🎜🎜🎜🎜Figure 15 Utilisez la méthode d'extension pour obtenir un nouveau DragDropService et marquez-le comme fourni au niveau racine🎜🎜🎜🎜🎜🎜🎜

    Figure 16 Vous pouvez utiliser le même sélecteur pour superposer des instructions répétées, superposer une instruction supplémentaire sur l'instruction Draggable et l'instruction Droppable de la bibliothèque de composants, et remplacer le jeton de DragDropService par le DragDropGlobalService qui a fourni un singleton à la racine

    As Comme le montrent les figures 15 et 16, via l'injecteur d'éléments, des instructions sont superposées pour remplacer le jeton DragDropService par une instance de notre propre singleton global. À l'heure actuelle, lorsque nous devons utiliser le singleton global DragDropService, il nous suffit d'introduire le module qui déclare et exporte ces deux instructions supplémentaires pour permettre à l'instruction Draggable Droppable de la bibliothèque de composants de communiquer entre les modules de chargement paresseux.

    Résumé des points de connaissance : Les injecteurs d'éléments ont une priorité plus élevée que les injecteurs de modules.

    3.5 Cas 5 : Comment attacher le menu déroulant au problème local dans le scénario de fonction de thème local

    Le thématisation de la bibliothèque de composants DevUI utilise des attributs personnalisés CSS (variables CSS) pour déclarer : la valeur de la variable CSS de root pour réaliser le changement de thème. Si nous souhaitons afficher des aperçus de différents thèmes en même temps dans une seule interface, nous pouvons re-déclarer les variables CSS localement dans l'élément DOM pour réaliser la fonction de thèmes locaux. Lorsque je créais auparavant un générateur de tramage de thème, j'utilisais cette méthode pour appliquer localement un thème.

    1Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 17 Fonction de thème local

    Mais il ne suffit pas d'appliquer simplement les valeurs des variables CSS localement. Il existe des calques contextuels déroulants qui sont attachés par défaut à l'arrière du corps, ce qui signifie que. leur couche d'attachement est en dehors des variables locales, ce qui entraînera un problème très embarrassant. La liste déroulante du composant de thème local affiche le style du thème externe.

    Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 18 Le thème de la liste déroulante de superposition attaché au composant externe dans le thème partiel est incorrect

    Que dois-je faire à ce moment-là ? Nous devrions déplacer le point d'attache à l'intérieur du domaine du thème local.

    On sait que l'Overlay du composant DatePickerPro de la bibliothèque de composants DevUI utilise l'Overlay d'Angular CDK Après une série d'analyses, nous l'avons remplacé par l'injection comme suit :

    1) Tout d'abord, nous héritons d'OverlayContainer et implémentons notre. propre ElementOverlayContainer comme indiqué ci-dessous.

    2Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 19 Personnalisez ElementOverlayContainer et remplacez la logique _createContainer

    2) Ensuite, fournissez directement notre nouveau ElementOverlayContainer du côté composant de l'aperçu, et fournissez un nouvel Overlay afin que le nouvel Overlay puisse utiliser notre OverlayContainer. À l'origine, Overlay et OverlayContainer étaient tous deux fournis sur root. Ici, nous devons couvrir ces deux éléments.

    2Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 20 Remplacez l'OverlayContainer par le ElementOverlayContainer personnalisé et fournissez une nouvelle Overlay

    À ce stade, accédez au site Web d'aperçu et le DOM de la couche contextuelle sera attaché avec succès à l'élément d'aperçu du composant. .

    2Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 21 Le conteneur Overlay de cdk est attaché au dom spécifié et l'aperçu partiel du thème est réussi

    Il existe également un OverlayContainerRef personnalisé dans la bibliothèque de composants DevUI pour certains composants et bancs de tiroirs de boîtes modales, qui également Il faut l'ajuster en conséquence pour le remplacement. Enfin, des fenêtres pop-up et des couches pop-up peuvent être réalisées pour prendre parfaitement en charge les thèmes locaux.

    Résumé des points de connaissance : De bons modèles d'abstraction peuvent rendre les modules remplaçables et obtenir une programmation d'aspect élégante.

    3.6 Cas 6 : CdkOverlay nécessite que l'instruction CdkScrollable soit ajoutée à la barre de défilement, mais elle ne peut pas être ajoutée à la couche la plus externe du composant d'entrée

    Quand il s'agit du dernier cas. , Je veux parler de certaines méthodes moins formelles. Il est pratique pour tout le monde de comprendre la nature du fournisseur. La configuration du fournisseur consiste essentiellement à le laisser vous aider à instancier ou à mapper une instance existante.

    Nous savons que si nous utilisons cdkOverlay, si nous voulons que la boîte contextuelle suive la barre de défilement et soit suspendue dans la bonne position, nous devons ajouter l'instruction cdkScrollable à la barre de défilement.

    C’est toujours la même scène que l’exemple précédent. Notre page entière est chargée via le routage. Pour plus de simplicité, j'ai écrit la barre de défilement sur l'hôte du composant.

    2Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 22 La barre de défilement de débordement de contenu écrit overflow:auto dans le composant:host

    De cette façon, nous rencontrons un problème plus difficile. Le module est spécifié par la définition du routeur, c'est-à-dire qu'il n'est pas affiché. n'importe où. Appelez <app-theme-picker-customize></app-theme-picker-customize> de la même manière, comment ajouter l'instruction cdkScrollable ? La solution est la suivante. Une partie du code est masquée ici et seul le code principal est laissé.

    2Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 23 Créer une instance par injection et appeler manuellement le cycle de vie

    Ici, une instance de cdkScrollable est générée par injection et le cycle de vie est appelé de manière synchrone pendant la phase du cycle de vie du composant.

    Cette solution n'est pas une méthode formelle, mais elle résout le problème. Elle est laissée ici comme une idée et une exploration au goût des lecteurs.

    Résumé des points de connaissance : Le fournisseur de configuration d'injection de dépendances peut créer des instances, mais veuillez noter que les instances seront traitées comme des classes de service ordinaires et ne peuvent pas avoir un cycle de vie complet.

    3.7 Plus de façons de jouer : personnalisez la plate-forme de remplacement pour réaliser l'interaction du framework Angular exécuté sur le terminal

    Vous pouvez vous référer à cet article de blog : "Rendering Angular applications in Terminal"

    2Compréhension approfondie du modèle dinjection de dépendances dans Angular (play case)

    Figure 24 Remplacement Le moteur de rendu RendererFactory2 et d'autres contenus permettent à Angular de s'exécuter sur le terminal. L'auteur a remplacé RendererFactory2 et d'autres moteurs de rendu pour permettre aux applications Angular de s'exécuter sur le terminal. C'est la flexibilité de la conception angulaire. Même la plate-forme peut être remplacée. Elle est puissante et flexible. Les détails détaillés du remplacement peuvent être trouvés dans l’article original et ne seront pas développés ici.

    Résumé des points de connaissance

    : La puissance de l'injection de dépendances est que le fournisseur peut la configurer lui-même et enfin implémenter la logique de remplacement.

    4 Résumé

    Cet article présente le mode d'injection de dépendances de l'inversion de contrôle et ses avantages. Il présente comment l'injection de dépendances dans Angular recherche les dépendances, comment configurer les fournisseurs et comment utiliser des décorateurs limités et filtrants pour obtenir le résultat souhaité. résultats. Les exemples requis sont ensuite utilisés pour analyser comment combiner les points de connaissance de l'injection de dépendances pour résoudre les problèmes rencontrés dans le développement et la programmation à travers N cas.

    Avec une bonne compréhension du processus de recherche de dépendances, nous pouvons configurer le fournisseur à l'emplacement exact (cas 1 et 2), remplacer d'autres instances par des singletons (cas 4 et 5) et même franchir les restrictions des packages de composants imbriqués Connect à l'exemple fourni (cas 3) ou utilisez la courbe de méthode fournie pour implémenter l'instanciation de l'instruction (cas 6).

    Le cinquième cas semble être un simple remplacement, mais pour pouvoir écrire une structure de code remplaçable nécessite une compréhension approfondie du mode d'injection et une abstraction meilleure et raisonnable de chaque fonction si l'abstraction ne l'est pas. approprié, ce ne sera pas possible. Profitez de l’injection de dépendances. Le mode d'injection offre plus d'espace possible pour que les modules soient enfichables, enfichables et basés sur des pièces, réduisant ainsi le couplage et augmentant la flexibilité, afin que les modules puissent fonctionner ensemble de manière plus élégante et harmonieuse.

    La puissante fonction d'injection de dépendances peut non seulement optimiser les chemins de communication des composants, mais plus important encore, elle peut également réaliser une inversion de contrôle, exposant les composants encapsulés à davantage d'aspects de la programmation, et la mise en œuvre de certaines logiques spécifiques à l'entreprise peut également devenir flexible.

    Pour plus de connaissances sur la programmation, veuillez visiter :

    Vidéos de programmation

     ! !

    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!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer