Maison > interface Web > js tutoriel > le corps du texte

Parlons du chargement paresseux des modules et de l'affichage dynamique de ses composants dans Angular

青灯夜游
Libérer: 2022-10-26 19:30:06
avant
1779 Les gens l'ont consulté

Comment charger paresseusement un module angular et créer dynamiquement les composants qui y sont déclarés sans routage ? L’article suivant va vous présenter la méthode, j’espère qu’elle vous sera utile !

Environnement : Angular 13.x.x

Angular prend en charge le chargement paresseux de certains modules de page via le routage pour réduire la taille du premier écran et améliorer la vitesse de chargement du premier écran. Mais cette façon de routage parfois le. la demande ne peut pas être satisfaite. [Recommandation de didacticiel connexe : "Tutoriel vidéo angulairejs"]

Par exemple, après avoir cliqué sur un bouton, une rangée de barres d'outils s'affichera. Je ne veux pas que ce composant de barre d'outils soit empaqueté dans main.js<.> par défaut, mais après que l'utilisateur a cliqué sur le bouton, le composant est chargé et affiché dynamiquement <code>main.js, 而是用户点按钮后动态把组件加载并显示出来.

那为什么要动态加载呢? 如果直接在目标页面组件引入工具栏组件, 那么工具栏组件中的代码就会被打包进目标页面组件所在的模块, 这会导致目标页面组件所在的模块生成的js体积变大; 通过动态懒加载的方式, 可以让工具栏组件只在用户点了按钮后再加载, 这样就可以达到减少首屏尺寸的目的.

为了演示, 新建一个angular项目, 然后再新建一个ToolbarModule, 项目的目录结构如图

为了达到演示的目的, 我在ToolbarModule的html模板中放了个将近1m的base64图片, 然后直接在AppModule中引用ToolbarModule, 然后执行ng build, 执行结果如图

可以看到打包尺寸到达了1.42mb, 也就是说用户每次刷新这个页面, 不管用户有没有点击显示工具栏按钮, 工具栏组件相关的内容都会被加载出来, 这造成了资源的浪费, 所以下面将ToolbarModuleAppModuleimports声明中移除, 然后在用户点击首次点击显示时懒加载工具栏组件.

懒加载工具栏组件

首先, 新建一个ToolbarModuleToolbarComponent, 并在ToolbarModule声明ToolbarComponent

toolbar.module.ts
import { NgModule } from &#39;@angular/core&#39;;
import { CommonModule } from &#39;@angular/common&#39;;
import { ToolbarComponent } from &#39;./toolbar.component&#39;;
 
@NgModule({
    declarations: [ToolbarComponent],
    imports: [CommonModule],
    exports: [ToolbarComponent],
})
class ToolbarModule {}
 
export { ToolbarComponent, ToolbarModule };
Copier après la connexion
toolbar.component.ts
import { Component, OnInit } from &#39;@angular/core&#39;;

@Component({
    selector: &#39;toolbar&#39;,
    templateUrl: &#39;./toolbar.component.html&#39;,
    styles: [
        `
    svg {
      width: 64px;
      height: 64px;
    }
    Parlons du chargement paresseux des modules et de laffichage dynamique de ses composants dans Angular {
      width: 64px;
      height: 64px;
      object-fit: cover;
    }
    `,
    ],
})
export class ToolbarComponent implements OnInit {
    constructor() {}

    ngOnInit(): void {}
}
Copier après la connexion
toolbar.component.html
<p class="flex">
  <svg t="1652618923451" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2104" width="200" height="200"><path d="M412 618m-348 0a348 348 0 1 0 696 0 348 348 0 1 0-696 0Z" fill="#C9F4EB" p-id="2105"></path><path d="M673.19 393h-333a25 25 0 0 1 0-50h333a25 25 0 0 1 0 50zM600.89 235H423.11C367.91 235 323 190.28 323 135.32v-12.5a25 25 0 0 1 50 0v12.5c0 27.39 22.48 49.68 50.11 49.68h177.78c27.63 0 50.11-22.29 50.11-49.68v-16.5a25 25 0 1 1 50 0v16.5c0 54.96-44.91 99.68-100.11 99.68zM673.19 585.5h-333a25 25 0 0 1 0-50h333a25 25 0 0 1 0 50zM467 778H340a25 25 0 0 1 0-50h127a25 25 0 0 1 0 50z" fill="#087E6A" p-id="2106"></path><path d="M739.76 952H273.62a125.14 125.14 0 0 1-125-125V197a125.14 125.14 0 0 1 125-125h466.14a125.14 125.14 0 0 1 125 125v630a125.14 125.14 0 0 1-125 125zM273.62 122a75.08 75.08 0 0 0-75 75v630a75.08 75.08 0 0 0 75 75h466.14a75.08 75.08 0 0 0 75-75V197a75.08 75.08 0 0 0-75-75z" fill="#087E6A" p-id="2107"></path></svg>
  <svg t="1652618941842"
       class="icon"
       viewBox="0 0 1024 1024"
       version="1.1"
       xmlns="http://www.w3.org/2000/svg"
       p-id="2247"
       width="200"
       height="200">
    <path d="M415 624m-348 0a348 348 0 1 0 696 0 348 348 0 1 0-696 0Z"
          fill="#C9F4EB"
          p-id="2248"></path>
    <path d="M695 790H362a25 25 0 0 1 0-50h333a25 25 0 0 1 0 50zM583 649H362a25 25 0 0 1 0-50h221a25 25 0 0 1 0 50zM262 287H129a25 25 0 0 1 0-50h133a25 25 0 0 1 0 50zM262 455.33H129a25 25 0 1 1 0-50h133a25 25 0 0 1 0 50zM262 623.67H129a25 25 0 0 1 0-50h133a25 25 0 0 1 0 50zM262 792H129a25 25 0 0 1 0-50h133a25 25 0 0 1 0 50z"
          fill="#087E6A"
          p-id="2249"></path>
    <path d="M761.76 964H295.62a125.14 125.14 0 0 1-125-125V209a125.14 125.14 0 0 1 125-125h466.14a125.14 125.14 0 0 1 125 125v630a125.14 125.14 0 0 1-125 125zM295.62 134a75.09 75.09 0 0 0-75 75v630a75.08 75.08 0 0 0 75 75h466.14a75.08 75.08 0 0 0 75-75V209a75.09 75.09 0 0 0-75-75z"
          fill="#087E6A"
          p-id="2250"></path>
    <path d="M617 376H443a25 25 0 0 1 0-50h174a25 25 0 0 1 0 50z"
          fill="#087E6A"
          p-id="2251"></path>
    <path d="M530 463a25 25 0 0 1-25-25V264a25 25 0 0 1 50 0v174a25 25 0 0 1-25 25z"
          fill="#087E6A"
          p-id="2252"></path>
  </svg>
  <Parlons du chargement paresseux des modules et de laffichage dynamique de ses composants dans Angular src="<这里应该是一张大小将近1M的base64图片, 内容较大, 就略去了...>" alt="">
</p>
Copier après la connexion

然后再AppComponent的中按钮点击事件处理程序中写加载工具栏模块的代码:

app.component.ts
import { Component, createNgModuleRef, Injector, ViewChild, ViewContainerRef } from &#39;@angular/core&#39;;

@Component({
    selector: &#39;root&#39;,
    template: `
               <p class="container h-screen flex items-center flex-col w-100 justify-center">
                 <p class="mb-3"
                      [ngClass]="{ hidden: !isToolbarVisible }">
                   <ng-container #toolbar></ng-container>
                 </p>
                 <p>
                   <button (click)="toggleToolbarVisibility()"
                           class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">{{ isToolbarVisible ? &#39;隐藏&#39; : &#39;显示&#39; }}</button>
                   <p class="mt-3">首屏内容</p>
                 </p>
               </p>
             `,
})
export class AppComponent {
    title = &#39;ngx-lazy-load-demo&#39;;
    toolbarLoaded = false;
    isToolbarVisible = false;
    @ViewChild(&#39;toolbar&#39;, { read: ViewContainerRef }) toolbarViewRef!: ViewContainerRef;

    constructor(private _injector: Injector) {}

    toggleToolbarVisibility() {
        this.isToolbarVisible = !this.isToolbarVisible;
        this.loadToolbarModule().then();
    }

    private async loadToolbarModule() {
        if (this.toolbarLoaded) return;
        this.toolbarLoaded = true;
        const { ToolbarModule, ToolbarComponent } = await import(&#39;./toolbar/toolbar.module&#39;);
        const moduleRef = createNgModuleRef(ToolbarModule, this._injector);
        const { injector } = moduleRef;
        const componentRef = this.toolbarViewRef.createComponent(ToolbarComponent, {
            injector,
            ngModuleRef: moduleRef,
        });
    }
}
Copier après la connexion

关键在于其中的第32-42行, 首先通过一个动态import导入toolbar.module.ts中的模块, 然后调用createNgModuleRef并传入当前组件的Injector作为ToolbarModule的父级Injector, 这样就实例化了ToolbarModule得到了moduleRef对象, 最后就是调用html模板中声明的<ng-container #toolbar></ng-container>ViewContainerRef对象的createComponent方法创建ToolbarComponent组件

private async loadToolbarModule() {
    if (this.toolbarLoaded) return;
    this.toolbarLoaded = true;
    const { ToolbarModule, ToolbarComponent } = await import(&#39;./toolbar/toolbar.module&#39;);
    const moduleRef = createNgModuleRef(ToolbarModule, this._injector);
    const { injector } = moduleRef;
    const componentRef = this.toolbarViewRef.createComponent(ToolbarComponent, {
        injector,
        ngModuleRef: moduleRef,
    });
}
Copier après la connexion

此时再来看下这番操作后执行ng build打包的尺寸大小

可以看到首屏尺寸没有开头那么离谱了, 原因是没有在AppModuleAppComponent直接导入ToolbarModuleToolbarComponent, ToolbarModule被打进了另外的js文件中(Lazy Chunk Files), 当首次点击显示按钮时, 就会加载这个包含ToolbarModule的js文件

注意看下面的gif演示中, 首次点击显示按钮, 浏览器网络调试工具中会多出一个对src_app_toolbar_toolbar_module_ts.js

Alors pourquoi doit-il être chargé dynamiquement si le composant barre d'outils est introduit directement dans le composant de la page cible, alors le code ? dans le composant de la barre d'outils sera empaqueté dans le module où se trouve le composant de la page cible, cela entraînera une augmentation de la taille du js généré par le module où se trouve le composant de la page cible grâce au chargement paresseux dynamique, le composant de la barre d'outils ; ne peut être chargé qu'après que l'utilisateur a cliqué sur le bouton, réduisant ainsi la taille du premier écran

Pour la démonstration, créez un nouveau projet angulaire, puis créez un nouveau ToolbarModule. le projet est comme indiqué

À des fins de démonstration, j'ai mis une image base64 de près de 1 million, puis j'ai référencé directement ToolbarModule dans AppModule, puis j'ai exécuté ng build, le le résultat de l'exécution est tel qu'indiqué dans la figure

🎜🎜🎜Vous pouvez voir que la taille de l'emballage a atteint 1,42 Mo, ce qui signifie que chaque fois que l'utilisateur actualise cette page, qu'il clique ou non sur le bouton Afficher la barre d'outils, le contenu lié au composant de la barre d'outils sera chargé, ce qui entraînera un gaspillage de ressources, donc ce qui suit sera ToolbarModule est supprimé de la déclaration imports de AppModule, puis charge paresseusement le composant de barre d'outils lorsque l'utilisateur clique sur le premier clic pour l'afficher. et ToolbarComponent, et déclarez ToolbarModuleToolbarComponent🎜🎜🎜
toolbar.module.tsrrreeerrreee détails>
toolbar.component.tsrrreee
toolbar.component.htmlrrreee
🎜Ensuite, écrivez le code pour charger le module de barre d'outils dans le gestionnaire d'événements de clic de bouton de AppComponent :🎜app.component.tsrrreee
🎜La clé se trouve dans les lignes 32 à 42. Tout d'abord, importez via un module dynamique <code>import dans toolbar.module.ts, puis appelez createNgModuleRef et transmettez le fichier. Injector du composant actuel en tant que parent de ToolbarModuleInjector, instanciant ainsi ToolbarModule et obtenant le moduleRef , et enfin appeler l'objet <ng-container d dans le mod html la m>createComponent</ng-container> de l'objet ViewContainerRef de la barre d'outils> crée le composant ToolbarComponent🎜rrreee🎜Jetons un coup d'oeil à ce moment. Après cette opération, exécutez ng build pour empaqueter la taille 🎜🎜 🎜🎜Vous pouvez voir que le la première taille d'écran n'est pas aussi scandaleuse qu'au début. La raison est qu'il n'y a pas de lien direct entre AppModule et AppComponent après l'importation de ToolbarModule. > et ToolbarComponent, ToolbarModule est importé dans un autre fichier js (Lazy Chunk Files). Lorsque est cliqué pour la première fois, le bouton , le js. Le fichier contenant <code>ToolbarModule sera chargé🎜🎜Veuillez regarder la démonstration gif ci-dessous, cliquez sur le bouton Afficher pour la première fois, dans l'outil de débogage du réseau du navigateur. Il y en aura un de plus demande du fichier src_app_toolbar_toolbar_module_ts.js🎜🎜🎜🎜🎜Pour plus de connaissances sur la programmation, veuillez visiter : 🎜Vidéo 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!

Étiquettes associées:
source:cnblogs.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal