查看ngIf
的粗略实现:
@Directive({ selector: '[myNgIf]'})
export class MyNgIfDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) { }
@Input() set myNgIf(condition: boolean) {
if (condition) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
}
}
最初设置getter和输入设置器并引发ngOnchanges
事件。这是ngInit
之前的第一个事件。
但是在那个setter中我们实际上正在使用viewContainer
(which is type of <ViewContainerRef>
) - 但是为什么它会在舞台上访问它?
问题
我期待看到这一行:
this.viewContainer.createEmbeddedView(this.templateRef) ,
- 在之后 - 已经可用的视图阶段,例如ngAfterViewInit
- 那么为什么它仍然有效并且可以访问查看容器?
我已经知道*
将其视为模板语法,但我仍然不了解视图容器在该阶段是如何可用的。
答案 0 :(得分:0)
您可能知道每个元素都可以用作视图容器。因此,应用于任何元素的指令可以将与其应用的元素关联的视图容器注入构造函数:
@Directive({
selector: '[adir]'
})
export class ADirective {
constructor(private vc: ViewContainerRef) {
console.log(this.vc.element.nativeElement.nodeName); // `DIV`
}
我可以将指令应用于任何元素:
<div adir></div>
这基本上是ngIf
访问视图容器的方式。
更有意思的是Angular进程@ViewChild查询before the digest starts,因此@ViewChild
中提供了静态ngOnInit
元素。这意味着你可以这样做:
@ViewChild('vc', {read: ViewContainerRef}) vc;
ngOnInit() {
this.vc; // already available
}