Heim  >  Artikel  >  Web-Frontend  >  Lassen Sie uns über das verzögerte Laden von Modulen und die dynamische Anzeige ihrer Komponenten in Angular sprechen

Lassen Sie uns über das verzögerte Laden von Modulen und die dynamische Anzeige ihrer Komponenten in Angular sprechen

青灯夜游
青灯夜游nach vorne
2022-10-18 20:46:091773Durchsuche

Wie lade ich ein eckiges Modul langsam und erstelle dynamisch die darin deklarierten Komponenten ohne Routing? Der folgende Artikel stellt Ihnen die Methode vor und ich hoffe, er wird Ihnen hilfreich sein!

Umgebung: Angular 13.x.x

angular unterstützt das verzögerte Laden bestimmter Seitenmodule durch Routing, um die Größe des ersten Bildschirms zu reduzieren und die Ladegeschwindigkeit des ersten Bildschirms zu verbessern Der Bedarf kann nicht gedeckt werden. [Verwandte Tutorial-Empfehlung: „AngularJS-Video-Tutorial“]

Nach dem Klicken auf eine Schaltfläche wird beispielsweise eine Reihe von Symbolleisten angezeigt. Ich möchte nicht, dass diese Symbolleistenkomponente in main.js standardmäßig, aber nachdem der Benutzer auf die Schaltfläche geklickt hat, wird die Komponente dynamisch geladen und angezeigt. <p><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 };
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;
    }
    Lassen Sie uns über das verzögerte Laden von Modulen und die dynamische Anzeige ihrer Komponenten in Angular sprechen {
      width: 64px;
      height: 64px;
      object-fit: cover;
    }
    `,
    ],
})
export class ToolbarComponent implements OnInit {
    constructor() {}

    ngOnInit(): void {}
}
toolbar.component.html
<p>
  <svg><path></path><path></path><path></path></svg>
  <svg>
    <path></path>
    <path></path>
    <path></path>
    <path></path>
    <path></path>
  </svg>
  <lassen sie uns das verz laden von modulen und die dynamische anzeige ihrer komponenten in angular sprechen>" alt="">
</lassen></p>

然后再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,
        });
    }
}

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

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

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

注意看下面的gif演示中, 首次点击显示按钮, 浏览器网络调试工具中会多出一个对src_app_toolbar_toolbar_module_ts.js Warum muss sie dann dynamisch geladen werden, wenn die Symbolleistenkomponente direkt in die Zielseitenkomponente eingeführt wird? Die Symbolleistenkomponente wird in das Modul gepackt, in dem sich die Zielseitenkomponente befindet. Dies führt dazu, dass die Größe der von dem Modul generierten JS, in der sich die Zielseitenkomponente befindet, durch dynamisches verzögertes Laden größer wird kann erst geladen werden, nachdem der Benutzer auf die Schaltfläche geklickt hat, wodurch die Größe des ersten Bildschirms reduziert wird.

Erstellen Sie zur Demonstration ein neues Winkelprojekt und erstellen Sie dann ein neues ToolbarModule Projekt ist wie gezeigt

Zu Demonstrationszwecken habe ich ein fast 1 m großes Base64-Bild eingefügt, dann direkt auf ToolbarModule in AppModule verwiesen und dann ng build ausgeführt Das Ausführungsergebnis ist wie in der Abbildung dargestellt

🎜🎜Sie können sehen, dass die Paketgröße 1,42 MB erreicht hat, was bedeutet, dass jedes Mal, wenn der Benutzer diese Seite aktualisiert, der Inhalt angezeigt wird, unabhängig davon, ob der Benutzer auf die Schaltfläche „Symbolleiste anzeigen“ klickt oder nicht Im Zusammenhang mit der Symbolleistenkomponente wird geladen, was zu einer Verschwendung von Ressourcen führt. Daher wird das folgende ToolbarModule aus der imports-Deklaration von AppModuleentfernt > und lädt dann die Symbolleistenkomponente träge, wenn der Benutzer auf den ersten Klick klickt, um sie anzuzeigen und ToolbarComponent und deklarieren Sie ToolbarModuleToolbarComponent🎜🎜🎜
toolbar.module.tsrrreee Details>
toolbar.component.tsrrreee
toolbar.component.htmlrrreee
🎜Dann schreiben Sie die Code zum Laden des Symbolleistenmoduls im Button-Click-Ereignishandler von AppComponent:🎜app.component.tsrrreee
🎜Der Schlüssel liegt in den Zeilen 32-42. Importieren Sie zuerst über ein dynamisches <code>import-Modul in toolbar.module.ts, rufen Sie dann createNgModuleRef auf und übergeben Sie das Injector der aktuellen Komponente als übergeordnetes Element von ToolbarModuleInjector, wodurch ToolbarModule instanziiert und die moduleRef abgerufen wird -Objekt und schließlich Aufruf des in der HTML-Vorlage deklarierten <ng-container die>createComponent</ng-container>-Methode des ViewContainerRef-Objekts der Symbolleiste> erstellt die Komponente ToolbarComponent 🎜🎜Sie können sehen, dass die Die erste Bildschirmgröße ist nicht mehr so ​​groß wie am Anfang. Der Grund dafür ist, dass es nach dem Import von ToolbarModulekeine direkte Verbindung zwischen AppModule und AppComponent gibt > und ToolbarComponent, ToolbarModule wird in eine andere js-Datei (Lazy Chunk Files) importiert. Wenn zum ersten Mal auf die Schaltfläche geklickt wird, wird die js Es wird eine Datei mit <code>ToolbarModule geladen🎜🎜Bitte sehen Sie sich die folgende GIF-Demonstration an. Klicken Sie zum ersten Mal auf die Schaltfläche Anzeigen. Im Netzwerk-Debugging-Tool des Browsers wird noch eine weitere angezeigt Anfrage für die Datei src_app_toolbar_toolbar_module_ts.js🎜🎜🎜🎜🎜Für mehr Programmierkenntnisse besuchen Sie bitte: 🎜Programmiervideo🎜! ! 🎜

Das obige ist der detaillierte Inhalt vonLassen Sie uns über das verzögerte Laden von Modulen und die dynamische Anzeige ihrer Komponenten in Angular sprechen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen