angular4 动态创建组件 vs 动态创建模板

有时候会有需要动态往页面里插入内容。

模拟场景:页面上帮助按钮的点击事件触发右边弹出帮助界面并加载帮助文档。(每个页面的帮助文档不一样)

//具体页面

export class xxComponent implements Oninit{ constructor(private helpingService:HelpingService){ } fileClick($event:any){ this.helpingService.changeHelpContent(comp); } }
//helping.service.ts

@Injectable()
export class HelpingService{ helpChangeEvent:EventEmitter
<comp>; //comp是动态组件 constractor(){ this.helpChangeEvent=new EventEmitter<comp>() } public changeHelpContent(comp){ this.helpChangeEvent.emit(comp) //页面上一个click的Event会触发helping组件的changeHelpContent函数 }
}
//helping.component.ts

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

export class HelpingComponent implements OnInit{
   constractor(private helpingService:HelpingService){
        this.helpingService.helpchangeEvent.subscribe((comp)=>{
               this.loadComponent(comp)     //加载组件
       })
   }
  
}

下面开始正式介绍相关需要了解动态创建组件和模板的相关知识点

1.TemplateRef

<template>元素会被封装成TemplateRef实例

通过TemplateRef实例,可以创建内嵌视图Embedded Views

@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);
     //页面中template绑定的元素=>一个comment元素
     let commentEle=this.tpl.elementRef.nativeElement;  
     //将绑定的元素的内容一步步渲染到页面上去
     view.rootNodes.forEach((node)=>{
         commentEle.parentNode.insertBefore(node,commentEle.nextSibling)
     })
 }
}

2.VIiewContainerRef

视图容器,是管理创建好的内嵌视图或组件视图

通过ViewContainerRef实例,可以基于TemplateRef创建内嵌视图,也可以基于ComponentFactoryResolver创建组件视图

当这个内容是相同的时候,可以使用动态创建内嵌视图 createEmbeddedView

如果每个页面的内容都不一样,则可以使用动态创建组件视图 createComponent

@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(){
     this.tplVcRef.createEmbeddedView(this.tplRef)
}
@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);
     this.conRef.createComponent(factory)
   }
 }

 
 

猜你喜欢

转载自www.cnblogs.com/artimis/p/9025238.html