<ng-template> 模板元素与html5的template元素一样,需要被特殊处理后才能渲染。ng主要是通过类TemplateRef和ViewContainerRef实现的。
通过阅读ngIf源码学习如何运用<ng-template>
在使用ngIf 指令时我们并未发现ng-template的身影,这是因为"*"(星号)语法糖的原因,这个简写方法是一个微语法,而不是通常的模板表达式, Angular会解开这个语法糖,变成一个<ng-template>标记,包裹着宿主元素及其子元素。
<div *ngIf="hero" >{{hero.name}}</div>
会被解析为
<ng-template [ngIf]="hero"> <div>{{hero.name}}</div> </ng-template>`
看下ngIf源码
import {Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef} from '@angular/core'; @Directive({selector: '[ngIf]'}) export class NgIf { private _context: NgIfContext = new NgIfContext(); private _thenTemplateRef: TemplateRef<NgIfContext>|null = null; private _elseTemplateRef: TemplateRef<NgIfContext>|null = null; private _thenViewRef: EmbeddedViewRef<NgIfContext>|null = null; private _elseViewRef: EmbeddedViewRef<NgIfContext>|null = null; constructor(private _viewContainer: ViewContainerRef, templateRef: TemplateRef<NgIfContext>) { this._thenTemplateRef = templateRef; } @Input() set ngIf(condition: any) { this._context.$implicit = this._context.ngIf = condition; this._updateView(); } @Input() set ngIfThen(templateRef: TemplateRef<NgIfContext>) { this._thenTemplateRef = templateRef; this._thenViewRef = null; // clear previous view if any. this._updateView(); } @Input() set ngIfElse(templateRef: TemplateRef<NgIfContext>) { this._elseTemplateRef = templateRef; this._elseViewRef = null; // clear previous view if any. this._updateView(); } private _updateView() { if (this._context.$implicit) { if (!this._thenViewRef) { this._viewContainer.clear(); this._elseViewRef = null; if (this._thenTemplateRef) { this._thenViewRef = this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context); } } } else { if (!this._elseViewRef) { this._viewContainer.clear(); this._thenViewRef = null; if (this._elseTemplateRef) { this._elseViewRef = this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context); } } } } } export class NgIfContext { public $implicit: any = null; public ngIf: any = null; }
ngIf的源码并不难,它的核心就在于_updateView函数,它主要通过ViewContainerRef的createEmbeddedView和clear方法来实现模板TemplateRef的呈现和清除(先不关注当中的then和else等的具体实现)。它使用TemplateRef取得<ng-template>的内容,并通过ViewContainerRef来访问这个视图容器。