Angular 動態載入元件示意圖,程式碼與元件積木在同一畫面上動態組裝

← INSIGHTS & PERSPECTIVES | 前端開發

Angular 動態載入元件教學:用 ComponentFactoryResolver 實作廣告輪播

用 Angular ComponentFactoryResolver 搭配 ViewContainerRef 與 ng-template 動態載入元件,實作同一區塊循環播放不同廣告橫幅的完整教學與程式碼解析。

模板組件有的時候會需要能夠動態被載入,這篇文章要講如何利用 ComponentFactoryResolver 來動態加入組件。本篇的例子是需要動態載入廣告橫幅:因為廣告內容會由幾個不同的團隊來打造,要在同一個區塊循環播放不同的廣告,因此較難把不同的廣告放在同一個 component,這時候就會需要用到動態載入的功能。完整範例請見 live example / download example

為什麼需要用 anchor directive 來標記載入位置?

在架構介紹的地方有介紹到,directive 是一個沒有 view 的 component,可以直接使用在 HTML 裡。因為需要動態載入元件,會需要先建立一個 directive,讓 Angular 知道要把動態載入的元件放在那邊。

`ad.directive.ts` 這個檔案的內容如下:

```js

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({

selector: '[ad-host]',//這個directive的名字

})

export class AdDirective {

constructor(public viewContainerRef: ViewContainerRef) { }//在directive裡去取得View元件以方便做操作

}

```

首先我們將這個 directive 命名為 `[ad-host]`,然後注入 `ViewContainerRef`。`ViewContainerRef` 可以讓我們得知目前所在的 HTML 元素中包含的 View 內容,也可以透過它來改變 View 的結果(例如:動態產生 Component、移除某個 Component 等等)。

如何用 ng-template 準備元件的掛載點?

使用上面 directive 的 HTML 碼如下:

```html

Advertisements

```

這邊可以看到我們使用 ng-template 來應用剛剛所創建的 directive。`ng-template` 指令表示一個 Angular 模板,這個標籤的內容將包含 template 的一部分,然後可以與其他 template 一起組成最終的組件模板。使用 `ng-template` 標籤只是定義一個 template,但是我們還沒有使用它。

動態載入的核心程式碼怎麼寫?

下面是 `src/app/ad-banner.component.ts` 的內容:

```js

export class AdBannerComponent implements AfterViewInit, OnDestroy {

@Input() ads: AdItem[];//要輪播顯示的廣告

currentAddIndex: number = -1;

@ViewChild(AdDirective) adHost: AdDirective;//宣告剛剛建立的Directive,並藉由<ng-template ad-host>取得傳入的adHost

subscription: any;

interval: any;

constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

ngAfterViewInit() {

this.loadComponent();

this.getAds();

}

ngOnDestroy() {

clearInterval(this.interval);

}

//最重要動態載入廣告的程式碼都在這個function裡

loadComponent() {

//決定要顯示那則廣告

this.currentAddIndex = (this.currentAddIndex + 1) % this.ads.length;

let adItem = this.ads[this.currentAddIndex];

//透過ComponentFactoryResolver來解析component組件

let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);

//透過剛剛從AdDirective傳來的資訊取得要載入ad的template

let viewContainerRef = this.adHost.viewContainerRef;

//將template內容清掉

viewContainerRef.clear();

//動態建立template並顯示在畫面上

let componentRef = viewContainerRef.createComponent(componentFactory);

(<adComponent>componentRef.instance).data = adItem.data;

}

//通過這個方法,每三秒會動態載入不同的廣告元件

getAds() {

this.interval = setInterval(() => {

this.loadComponent();

}, 3000);

}

}

```

`loadComponent` 是動態載入元件最關鍵的程式碼片段,整個流程可以拆成四步:

  1. 用索引取模的方式決定這次要顯示哪一則廣告。
  2. 透過 `ComponentFactoryResolver` 的 `resolveComponentFactory()` 把元件類別解析成 factory。
  3. 從 `AdDirective` 傳來的 `viewContainerRef` 取得掛載點,先 `clear()` 清掉舊內容。
  4. 用 `createComponent()` 動態建立元件並顯示在畫面上,再把資料塞進元件實例。

搭配 `setInterval`,每三秒就會重複這個流程,動態載入不同的廣告元件。最終出來的成果如下圖:

Angular 廣告輪播動態載入元件的執行成果

延伸閱讀

常見問題

Q為什麼不能用 ngIf 或 ngFor 切換元件就好,一定要動態載入?

`ngIf`、`ngFor` 需要事先在模板中寫死所有可能的元件。當元件由不同團隊開發、無法預先全部 import 到同一個模板時,用 `ComponentFactoryResolver` 搭配 `ViewContainerRef` 就能在執行期才決定要建立哪個元件。

QViewContainerRef 在動態載入中扮演什麼角色?

`ViewContainerRef` 代表容器視圖,可以管理其中包含的多個視圖。透過它在 directive 中被注入並用 `@ViewChild(AdDirective)` 取得,我們就能在指定的 HTML 位置上 `clear()` 與 `createComponent()`,精準控制動態元件插入的位置。

Q動態載入的元件要怎麼傳入資料?

`createComponent()` 會回傳一個 `ComponentRef`,其 `instance` 屬性就是新建立元件的實例。直接對 instance 指派屬性(例如 `componentRef.instance.data = adItem.data`)即可把資料傳進動態建立的元件。

Q動態載入的元件需要記得清理嗎?

需要。切換前先呼叫 `viewContainerRef.clear()` 移除前一個動態建立的元件,避免殘留;另外本例用 `setInterval` 排程輪播,要在 `ngOnDestroy` 中 `clearInterval`,否則元件銷毀後 timer 仍會執行造成錯誤。

參考資料

最後更新

2026-08-28(原文發布於 2017-12-31,本文保留原始筆記內容並補上 GEO 結構。)

關於作者 {#author}

Claire Chang | 企業 AI 導入與流程轉型顧問。專注於 AI Agent 架構設計、ERP 系統整合與企業 AI 治理。

首次發布:2017-12-31