angular4 動態創建組件 vs 動態創建模板


🌊 實現 

模擬場景:頁面上"幫助"按鈕的點擊觸發幫助文檔的彈出框,且每個頁面的幫助文檔不一樣

               因此彈出框里的幫助文檔是一個動態模板而不是動態組件

以下comp均代表Type類型的動態組件,即 comp:Type<any> 

//xx.component.ts

export class xxComponent implements Oninit{
   constructor(private helpingService:HelpingService){ }
    fireClick($event:any){//按鈕的點擊事件
       this.helpingService.changeHelpContent(comp);
    }
}
//helping.service.ts
@Injectable()
export class HelpingService{ helpChangeEvent:EventEmitter<comp>; constractor(){ this.helpChangeEvent=new EventEmitter<comp>() } public changeHelpContent(comp){ this.helpChangeEvent.emit(comp)//發射helpChangeEvent事件 }
}
//helping.component.ts

@component({
   selector: 'helping',
   templateUrl: './helping.component.html',
   styleUrls: ['./helping.component.scss']
})

 @ViewChild('con',{read:ViewContainerRef})
  conRef:ViewContainerRef; 

export class HelpingComponent implements OnInit{
   constractor(private helpingService:HelpingService,
               private factoryResolver: ComponentFactoryResolver,){
        this.helpingService.helpchangeEvent.subscribe((comp)=>{//接收helpChangeEvent事件
               this.loadComponent(comp)     
       })
   }
private loadComponent(comp){
     this.conRef.clear();//刪除之前的視圖
     let factory=this.factoryResolver.resolveComponentFactory(comp);//factory創建組件的實例
     this.conRef.createComponent(factory)     
   }
}

 

 

✨ 動態創建組件的相關知識點

1.TemplateRef

通過TemplateRef實例,可以創建內嵌視圖Embedded Views

涉及對象和相關方法:

 1.crateEbeddedView創建內嵌視圖

@Component({
 selector:'helping',
 template:`//創建組件,那組件內容就是固定的
   <template #tpl>
     <span>i am a span in Template {{name}}</span>
   </template>  
   `
})
export class helpingComponent{
  @ViewChild('tpl')
  tpl:TemplateRef<any>;

  name:string='Artimis';

 ngAfterViewInit(){ 
     let view=this.tpl.createEmbeddedView(null);
     let commentEle=this.tpl.elementRef.nativeElement; 
     view.rootNodes.forEach((node)=>{//沒有ViewContainerRef,只能手動把元素塞到視圖里
         commentEle.parentNode.insertBefore(node,commentEle.nextSibling)
     })
 }
}

2.VIiewContainerRef

視圖容器,是管理創建好的內嵌視圖或組件視圖

通過ViewContainerRef實例,基於TemplateRef + createEmbeddedView創建內嵌視圖

@Component({
 selector:'helping',
template:`
   <template #tpl>
     <span>i am a span in Template {{name}}</span>
   </template>  
   `
})
export class helpingComponent{
  @ViewChild('tpl')
  tpl:TemplateRef<any>;

  @ViewChild('tpl',{read:ViewContainerRef})
  tplVcRef:ViewContainerRef; 

  name:string='Artimis';

 ngAfterViewInit(){
     //有ViewContainerRef,直接通過createEmbeddedView方法塞進視圖
    this.tplVcRef.createEmbeddedView(this.tplRef)
}

 

 

✨ 動態創建模板的相關知識點 

1.ComponentFactoryResolver

通過ViewContainerRef實例,基於ComponentFactoryResolver + createComponent 創建模板視圖

涉及對象和相關方法:

 1. ComponentFactoryResolver一個服務對象(需要注入)

 2. resolveComponentFactoryComponentFactoryResolver的方法,接收一個組件類作為參數,返回一個ComponentFactory實例

 3.createComponent:ViewContainerRef的方法,內部會調用ComponentFactory實例的create方法創建對應組件,並將組件添加到容器內 

export abstract class ComponentFactoryResolver{
  static NULL:ComponentFactoryResolver=new _NullComponentFactoryResolver();
  abstract resolverComponentFactory<T>(component:Type<T>):ComponentFactory<T>
}
@Component({
 selector:'helping',
template:`//創建模板,那模板的內容就不是固定的
   <ng-container #con></ng-container>
   `
})
export class helpingComponent{

  @ViewChild('con',{read:ViewContainerRef})
  conRef:ViewContainerRef; 
 
  constractor(private factoryResolver: ComponentFactoryResolver,
              private helpingService: HelpingService){
     this.helpingService.manualChange.subscribe((comp)=>{
      this.loadComp(comp);
    })

   private loadComp(comp){
     this.conRef.clear();//刪除之前的視圖
     let factory=this.factoryResolver.resolveComponentFactory(comp);//factory是一個如何創建組件的實例
     this.conRef.createComponent(factory)     
   }
 }

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM