詳解Angular動態元件
使用場景
我們先明確下動態元件的使用場景,在程式碼執行時要動態載入元件,換成普通人話,程式碼需要根據具體情況(比如使用者的操作,向後臺請求結果)確定在某些地方載入某些元件,這些元件不是靜態的(不是固定的)。
官網的舉例就是,構建動態廣告條,廣告元件不斷會推出新的,再用只支援靜態元件結構的模板顯然是不現實的。
再舉一個常見的例子,動態彈出框,彈出的元件是不確定的、不斷更新的,這裡那裡彈出個購買框,那那那又需要彈出樣式選擇框,靜態元件結構模板是不能滿足群眾日漸增長的需求。
怎麼實現
然後我們來找個把手,看實現動態元件需要什麼。
一、動態元件放在哪
我們需要知道把動態元件加在哪裡,也就是錨點。那什麼東西可以用來載入元件呢?
你可能會想說,元件不就載入錨點上嗎,錨點不就是DOM節點嗎?那當然是載入DOM節點裡啊。
我們先來回顧下Angular操作DOM的常見方法,原生jshttp://www.cppcns.com操作DOM的方法你就不要想了,你覺得它能返回給你能載入Angular元件的物件嗎?
Angulhttp://www.cppcns.comar 提供了一種叫做 DOM Query 的技術,主要來源於 @ViewChild 和 @ViewChildren 裝飾器(decorators),兩者基本功能相同 。
@ViewChild: 返回單個引用,在檢視的 DOM 中查詢能匹配上該選擇器的第一個元素或指令。
@ViewChildren :返回由 QueryList 物件包裝好的多個引用,在檢視的 DOM 中查詢能匹配上該選擇器的所有元素或指令。
基本語法:
@ViewChild([reference from template],{read: [reference type]});
DOM Query 的技術查找出來的物件分為三類:
ElementRef:如果它掛載的是類似 span 的簡單 html 元素;
TemplateRef: 如果它掛載的是 template 元素;
ViewContainerRef: 無法推斷,一般要程式設計師要在read中指明,任何DOM元素都可以被用作為檢視容器。
我們通過官網查詢API可以看到只有ViewContainerRef才是可以將一個或多個檢視附著到元件中的容器,也就是隻有它才可以載入元件。不過要注意的是,它是一個可以將新的元件作為其兄弟(節點)的DOM元素(容器),是兄弟,不是父子額。
好的,我們確定了使用ViewContainerRef來載入容器,獲取ViewContainerRef有兩種方式:
第一種就是上面的通過DOM Query查詢@ViewChild獲取
<ng-container #addComp></ng-container> @ViewChild('addComp',{read: ViewContainerRef}) adComp:ViewContainerRef;
第二種就是官網裡的例子,用依賴注入
import { Directive,程式設計客棧ViewContainerRef } from '@angular/core'; @Directive({ selector: '[ad-host]',}) export class AdDirective { constructor(public viewContainerRef: ViewContainerRef) { } }
錨點設定ng-template上,通過指令注入獲取ViewContainerRef
template: ` <div class="ad-banner-example"> <h3>Advertisements</h3> <ng-template ad-host></ng-template> </div>
二、怎麼獲取元件的例項
元件載入到檢視中去,不是簡單一個new就例項化,再append、insert之類就能附加上去的就可以的。動態元件需要編譯器事先編譯存放好起來,再以ComponentFactory封裝起來,之後的Component例項要通過ComponentFactory 來建立。大家可以看下這篇文章[譯] 關於 Angular 動態元件你需要知道的,不過它提及的使用 SystemJsNgModuleLoader 模組載入器已經被淘汰了。
ComponentFactoryResolver一個簡單的登錄檔,對映Components到ComponentFactory可用於建立元件例項的生成的類。它可用於獲取給定元件型別的工廠,然後使用工廠的create()方法建立該型別的元件。
我們來看下官網例項程式碼,以下不是完整程式碼
//注入ComponentFactoryResolver constructor(private componentFactoryResolver: JqIOWPSComponentFactoryResolver) { } loadComponent() { ...... // 拿到可用於建立廣告元件例項的生成的ComponentFactory const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component); //獲取載入元件的容器 const viewContainerRef = this.adHost.viewContainerRef; viewContainerRef.clear(); // 把元件放到容器裡,再傳一些引數給它 const componentRef = viewContainerRef.createComponent(componentFactory); (<AdComponent>componentRef.instance).data = adItem.data; }
你以為這就完了,你以為這樣寫出的程式碼就能執行嗎?太年輕,讓前浪來給你說一下要注意的幾個點:
Angular 中的元件、指令、管道都是是被封裝在模組中,以元件為例,如果要使用其別的模組元件,必須別的模組有export這個元件,而且你在自己模組也要import其他模組。所以官網www.cppcns.com例子的指令記得匯入匯出。
如果是動態元件,必須把元件註冊在模組中 entryComponents 屬性,但是就不用了export,import模組還是需要的。
以上就是詳解Angular動態元件的詳細內容,更多關於Angular動態元件的資料請關注我們其它相關文章!