ViewContainerRef 可以包含一个或者多个视图的容器
TemplateRef 内嵌模板,可用来创建内嵌视图
EmbeddedViewRef 内嵌视图
假设ts中注入private viewContainerRef:ViewContainerRef ,private templateRef:TemplateRef 两个服务
在ViewContainerRef 和TemplateRef 中都有createEmbeddedView创建视图的方法,所以往ViewContainerRef 容器插入视图的时候可以有两种方式:
1、this.viewContainerRef.createEmbeddedView(this.tmplateRef,context?)
第一种方法由ViewContainerRef 容器创建EmbeddedViewRef视图,然后插入TemplateRef模板,context是设置的模板内容。
2、this.viewContainerRef.inster(this.templateRef.createEmbeddedView(context?),index?)
第二种方法由TemplateRef 模板创建EmbeddedViewRef 视图,ViewContainerRef 容器调用自身的inster 方法直接插入,index为视图插入容器的位置索引,索引从0开始
代码演示
html代码
<div class="box" #box>
<button class="btn btn-primary mr-1" (click)="insert(secondTpl)">insert second</button>
<button class="btn btn-primary mr-1" (click)="insert(thirdTpl)">insert third</button>
<button class="btn btn-primary mr-1" (click)="insert(fourthTpl)">insert fourth</button>
<button class="btn btn-primary mr-1" (click)="insertAll()">insert all</button>
<button class="btn btn-secondary mr-1" (click)="insertFree()">insert free</button>
<button class="btn btn-info mr-1" (click)="getOne()">get one</button>
<button class="btn btn-success mr-1" (click)="move()">move free</button>
<button class="btn btn-success mr-1" (click)="move2To4()">把第二个移动到第四个位置上</button>
<button class="btn btn-success" (click)="move2ToOther()">把第二个移动到其他容器中</button>
<p>长度:{{ firstContain?.length }}</p>
</div>
<ng-template #firstTpl>
<p>first tpl content</p>
</ng-template>
<ng-template #secondTpl>
<p>第二段template</p>
</ng-template>
<ng-template #thirdTpl>
<p>第三段template</p>
</ng-template>
<ng-template #fourthTpl>
<p>第四段template</p>
</ng-template>
<ng-template #freeTpl>
<p>自由的template</p>
</ng-template>
<p>
first container:
<ng-container #firstContainer></ng-container>
</p>
<hr>
<p>
second container:
<ng-container #secondContainer></ng-container>
</p>
ts代码
import {
AfterViewInit,
Component,
EmbeddedViewRef,
OnInit,
TemplateRef,
ViewChild,
ViewContainerRef
} from '@angular/core';
@Component({
selector: 'app-tpl-container',
templateUrl: './tpl-container.component.html',
styleUrls: ['./tpl-container.component.scss']
})
export class TplContainerComponent implements OnInit,AfterViewInit {
@ViewChild('firstTpl', {read: TemplateRef}) readonly firstTpl: TemplateRef<any>
@ViewChild('secondTpl', {read: TemplateRef}) readonly secondTpl: TemplateRef<any>
@ViewChild('thirdTpl', {read: TemplateRef}) readonly thirdTpl: TemplateRef<any>
@ViewChild('fourthTpl', {read: TemplateRef}) readonly fourthTpl: TemplateRef<any>
@ViewChild('freeTpl', {read: TemplateRef}) readonly freeTpl: TemplateRef<any>
@ViewChild('firstContainer', {read: ViewContainerRef, static: true}) firstContain: ViewContainerRef
@ViewChild('secondContainer', {read: ViewContainerRef, static: true}) secondContain: ViewContainerRef
private freeView: EmbeddedViewRef<any>
constructor() {
}
ngOnInit(): void {
}
ngAfterViewInit(): void {
setTimeout(() => {
this.firstContain.createEmbeddedView(this.firstTpl);
},0);
this.freeView = this.freeTpl.createEmbeddedView({$implicit:'defaultValue',free:'free'});
}
insert(tpl: TemplateRef<any>) {
this.firstContain.insert(tpl.createEmbeddedView(null));
}
insertAll() {
[this.secondTpl, this.thirdTpl, this.fourthTpl].forEach(tpl => {
this.firstContain.insert(tpl.createEmbeddedView(null));
});
}
insertFree() {
this.firstContain.insert(this.freeView);
}
getOne() {
let view = this.firstContain.get(2);
console.log("view", view);
}
move() {
this.firstContain.move(this.freeView, 1);
}
move2To4() {
let view = this.firstContain.detach(1);
this.firstContain.insert(view, 3);
}
move2ToOther() {
let view = this.firstContain.detach(1);
this.secondContain.insert(view);
}
}