有时候会有需要动态往页面里插入内容。
模拟场景:页面上帮助按钮的点击事件触发右边弹出帮助界面并加载帮助文档。(每个页面的帮助文档不一样)
//具体页面
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) } }