使用到動態組件是由於我在作一個Table的控件,表格中有按鈕等控件,並具備相應邏輯,同時項目中多處使用到該表格,故想提取一個可複用的控件以減小工做量。主要參考的文章是大神的修仙之路Angular 4.x 動態建立組件以及官方文檔Dynamic Component Loader;html
這裏主要簡要記錄一下我本身的理解。segmentfault
ng generate component test
import { TestComponent } from '.../test.component' import { CommonModule } from '@angular/common'; @NgModule({ imports: [ ... ], declarations: [ ..., TestComponent ], entryComponents: [TestComponent] })
*注意最後咱們用了一個entryComponent的命令,這是由於通常而言,angular編譯器會根據代碼自動生成全部組件的ComponentFactory,但對於動態插入的組件,其在父組件的代碼中沒有對於的模板選擇器(eg:<test></test>),故爲了能讓編譯器能生成動態組件的ComponentFactory,須要人手告訴angular去生成。瀏覽器
Generally, the Angular compiler generates a ComponentFactory for any component referenced in a template. However, there are no selector references in the templates for dynamically loaded components since they load at runtime.To ensure that the compiler still generates a factory, add dynamically loaded components to the NgModule's entryComponents array:app
*ComponentFactory代碼定義以下,個人理解它是angular編譯得出的js方法,交給瀏覽器運行,從而用來實際建立組件;ide
class ComponentFactory<C> { get selector: string get componentType: Type<any> get ngContentSelectors: string[] get inputs: {...} get outputs: {...} create(injector: Injector, projectableNodes?: any[][], rootSelectorOrNode?: string | any, ngModule?: NgModuleRef<any>): ComponentRef<C> }
*entryComponent則告訴angular編譯器,在用戶交互過程當中,須要動態生成某個組件,故命令angular生成該組件的ComponentFactory,以供後續組件的動態建立使用。
*導入CommonModule,是爲了其後使用ngIf,ngFor,<ng-template>等指令。ui
... import { ViewContainerRef, AfterViewInit, ViewChild, ComponentFactoryResolver} from '@angular/core'; import { TestComponent } from '.../test.component' ... export class ParentComponent{ @ViewChild("Container", { read: ViewContainerRef }) vcRef: ViewContainerRef; constructor(private componentFactoryResolver: ComponentFactoryResolver) { } ... ngAfterViewInit() { let componentFactory = this.componentFactoryResolver.resolveComponentFactory(TestComponent); this.vcRef.clear(); let dynamicComponent = vcRef.createComponent(componentFactory); ... } }
<ng-template #Container></ng-template>
*ViewContainerRef 類型表明裝載視圖的容器類this
Represents a container where one or more Views can be attached
*ViewChild用於獲取對應ViewContainerRef中的第一個元素或對應的ViewContainerRef實例code
You can use ViewChild to get the first element or the directive matching the selector from the view DOM. If the view DOM changes, and a new child matches the selector, the property will be updated.
*此處利用定義html錨點#container,當實例化ViewChild時,傳入第一個參數爲錨點名字「container」,第二個參數{read: <Type>}爲查詢條件,設置查詢的類型,此處設置返回ViewContainerRef的實例;component
*componentFactoryResolver提供生成componentFactory的方法;htm
*因爲ViewChild所進行的視圖查詢是在ngAfterViewInit前調用的,因此對vcRef的操做要在ngAfterViewInit後進行,不然vcRef是undefined,最後利用vcRef的createComponent方法,根據生成的componentFactory,可動態組件;
*對組件dynamicComponent的操做,可經過如下代碼進行,例如,動態組件TestComponent中有@Input() Data,可經過.data進行賦值;
(<any>dynamicComponent.instance).data = "test";
至此,爲我對動態組件的理解。利用動態組件的Table控件實現會整理進下一篇文章。