首頁  >  文章  >  web前端  >  聊聊Angular中懶加載模組並動態顯示它的元件

聊聊Angular中懶加載模組並動態顯示它的元件

青灯夜游
青灯夜游轉載
2022-10-18 20:46:091787瀏覽

不通過路由的情況下, 怎麼懶加載一個angular模組,並動態創建其中聲明的組件?以下這篇文章跟大家介紹一下方法,希望對大家有幫助!

環境: Angular 13.x.x

angular中支援可以透過路由來懶載入某些頁面模組已​​達到減少首螢幕尺寸, 提高首屏載入速度的目的. 但是這種通過路由的方式有時候是無法滿足需求的。 【相關教學推薦:《angularjs影片教學》】

例如, 點擊一個按鈕後顯示一行工具列, 這個工具列元件我不希望它預設會打包進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 '@angular/core';
import { CommonModule } from '@angular/common';
import { ToolbarComponent } from './toolbar.component';
 
@NgModule({
    declarations: [ToolbarComponent],
    imports: [CommonModule],
    exports: [ToolbarComponent],
})
class ToolbarModule {}
 
export { ToolbarComponent, ToolbarModule };
toolbar.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'toolbar',
    templateUrl: './toolbar.component.html',
    styles: [
        `
    svg {
      width: 64px;
      height: 64px;
    }
    聊聊Angular中懶加載模組並動態顯示它的元件 {
      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>
  " alt="">
</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檔案的請求

更多程式相關知識,請造訪:程式設計影片! !

以上是聊聊Angular中懶加載模組並動態顯示它的元件的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除