1、自定義元素
答:即瀏覽器允許用戶自定義標簽來擴展HTML,也稱之為web Component,當將自定義標簽添加到CustomElementRegistry(自定義元素注冊表)中之后就會被瀏覽器識別,可在HTML的任何位置使用。在angular中可以通過自定義元素標簽將angular組件(包括變更檢測機制和數據綁定功能)插入到不受angular控制的HTML內容中,可用於替代動態組件
2、如何將angular組件轉換為自定義元素
答:
a、使用angular內置模塊@angular/el ements中的createCustomElement(ComponentClass)方法將傳入的組件類轉換為NgElementConstructor類型的構造器類
b、使用瀏覽器內置的customElements.define()方法,將自定義標簽名和第一步根據angular組件生成的自定義元素標簽構造器類一同傳入其中,完成向瀏覽器的CustomElementRegistry(自定義元素注冊表)中注冊此自定義元素標簽的過程
c、在html中使用此自定義元素標簽時,瀏覽器會使用此標簽對應的構造器類創建一個自定義元素標簽的實例
注意:angular組件中的輸入和輸出屬性對應到自定義元素標簽上就是Attribute和瀏覽器的自定義事件,且自定義輸出屬性傳遞的數據被存放在自定義事件的事件對象中的detail屬性中,並且保留着變更檢測和數據綁定的功能,同時需要在angular的根模塊的@NgModule裝飾器對象屬性entryComponent中添加此組件
3、為自定義元素標簽提供類型支持
答:使用在angular的@angular/elements模塊中提供的NgElement和WithProperties<T>兩個類型。
NgElement:是對HTMLElement類型的擴展
WithProperties<T>:來說明angular組件中定義的其它輸入和輸出屬性
有兩種方式提供:
a、直接在使用的地方提供:
如:document.createElement('my-custom-tag') as NgElement & WithProperties<{inputAttr: string}>
b、創建一個擴展HTMlElementTagNameMap接口的類型文件,用來集中聲明自定義元素標簽的類型
如:
declare global {
interface HTMLElementTagNameMap {
'my-custom-tag': NgElement & WithProperties<{inputAttr: string}>
}
}
4、動態組件
答:即在應用程序運行期間根據需要動態加載的一類組件,需要提前添加到根模塊的@NgModule裝飾器對象的entryComponent屬性中
5、創建及使用動態組件
答:有兩種方式創建並使用動態組件:
> 通過angular內置的ViewContainerRef類的createComponent()方法創建動態組件,該種方式適用於angular13版本之后,具體步驟:
a、將需要作為動態組件使用的組件添加到跟模塊的@NgModule裝飾配置對象的entryComponent屬性中
b、在需要使用動態組件的模板中指定插入動態組件的位置,如:
<ng-template #dynamicComContainer></ng-template>
c、在需要使用動態組件的組件類中使用@ViewChild裝飾器獲取插入位置的視圖容器引用,如:
@ViewChild(ViewContainerRef) viewRef !: ViewContainerRef;
d、使用ViewContainerRef類中提供的createComponent方法創建組件引用並向視圖容器中插入該組件,
且createComponent方法會返回一個ComponentRef,即所創建的組件實例的引用,通過該引用可以實現與動態組件之間的交互
> 通過angular內置的ComponentFactoryResolver類的resolveComponentFactory()方法創建對應組件類型的工廠類ComponentFactory,使用該工廠類的create方法創建該類型的組件,並在此方法的第三個參數指定插入該組件實例的頁面位置(即一個dom標簽元素,也可以是自定義標簽元素),然后將該dom元素插入到DOM中即可。此種方式適用於angular13之前的版本,具體步驟如下:
a、通過const customEle = document.createElement('my-tag')創建一個用於插入組件視圖的元素
b、通過ComponentFactoryResolver類提供的resolveComponentFactory(comClass)方法傳入組件類,以解析出該組件的組件工廠類ComponentFactory
c、使用上一步解析出的工廠類ComponentFactory的create(this.injector, [], customEle)方法,並在該方法的第三個參數中傳入第一步創建的好的自定義元素,以完成組件的動態創建以及插入到指定的dom元素中(此處是customEle標簽元素中)
d、將第一步創建的標簽元素添加到HTML中的指定位置即可:body.append(customEle);
注意:工廠類ComponentFactory的create方法返回當前創建的組件實例的引用ComponentRef,可就此引用來和該組件進行交互和數據傳遞
注意:在@ContentChild和@ViewChild的第二個參數對象中static為true時可以在ngOnInit鈎子中訪問到定義的變量,為false時只能在對應的ngAfterContentInit和ngAfterViewInit鈎子中查詢到值