详解Angular 4.x NgIf 的用法

ngIf 指令用于根据表达式的值,在指定位置渲染 then 或 else 模板的内容。

then 模板除非绑定到不同的值,否则默认是 ngIf 指令关联的内联模板。

else 模板除非绑定对应的值,否则默认是 null。

NgIf 指令语法

简单形式

<!--语法糖--> <div *ngIf="condition">...</div> <!--Angular 2.x中使用template--> <ng-template [ngIf]="condition"><div>...</div></ng-template>

使用else块

<div *ngIf="condition; else elseBlock">...</div> <ng-template #elseBlock>...</ng-template>

使用then和else块

<div *ngIf="condition; then thenBlock else elseBlock"></div> <ng-template #thenBlock>...</ng-template> <ng-template #elseBlock>...</ng-template>

使用as语法

<div *ngIf="condition as value; else elseBlock">{{value}}</div> <ng-template #elseBlock>...</ng-template>

NgIf 使用示例

@Component({ selector: 'ng-if-then-else', template: ` <button (click)="show = !show">{{show ? 'hide' : 'show'}}</button> <button (click)="switchPrimary()">Switch Primary</button> show = {{show}} <br> <div *ngIf="show; then thenBlock; else elseBlock">this is ignored</div> <ng-template #primaryBlock>Primary text to show</ng-template> <ng-template #secondaryBlock>Secondary text to show</ng-template> <ng-template #elseBlock>Alternate text while primary text is hidden</ng-template> ` }) class NgIfThenElse implements OnInit { thenBlock: TemplateRef<any> = null; show: boolean = true; @ViewChild('primaryBlock') primaryBlock: TemplateRef<any> = null; @ViewChild('secondaryBlock') secondaryBlock: TemplateRef<any> = null; switchPrimary() { this.thenBlock = this.thenBlock === this.primaryBlock ? this.secondaryBlock : this.primaryBlock; } ngOnInit() { this.thenBlock = this.primaryBlock; } }

基础知识

TemplateRef
TemplateRef 实例用于表示模板对象,TemplateRef 抽象类的定义如下:

// angular\packages\core\src\linker\template_ref.ts export abstract class TemplateRef<C> { abstract get elementRef(): ElementRef; abstract createEmbeddedView(context: C): EmbeddedViewRef<C>; }

ViewContainerRef

ViewContainerRef 实例提供了 createEmbeddedView() 方法,该方法接收 TemplateRef 对象作为参数,并将模板中的内容作为容器 (comment 元素) 的兄弟元素,插入到页面中。

NgIfContext

NgIfContext 实例用于表示 NgIf 上下文。

// angular\packages\common\src\directives\ng_if.ts export class NgIfContext { public $implicit: any = null; public ngIf: any = null; }

NgIf 源码分析

NgIf 指令定义

@Directive({ selector: '[ngIf]' // 属性选择器 - <ng-template [ngIf]="condition"> })

NgIf 类私有属性及构造函数

export class NgIf { // 创建NgIfContext上下文 private _context: NgIfContext = new NgIfContext(); // 表示then模板对象 private _thenTemplateRef: TemplateRef<NgIfContext>|null = null; // 表示else模板对象 private _elseTemplateRef: TemplateRef<NgIfContext>|null = null; // 表示根据then模板创建的EmbeddedViewRef视图 private _thenViewRef: EmbeddedViewRef<NgIfContext>|null = null; // 表示根据else模板创建的EmbeddedViewRef视图 private _elseViewRef: EmbeddedViewRef<NgIfContext>|null = null; constructor( private _viewContainer: ViewContainerRef, templateRef: TemplateRef<NgIfContext>) { this._thenTemplateRef = templateRef; // then模板的默认值为ngIf指令关联的内联模板 } }

NgIf 类输入属性

@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; // 清除之前创建的视图 this._updateView(); } @Input() set ngIfElse(templateRef: TemplateRef<NgIfContext>) { this._elseTemplateRef = templateRef; this._elseViewRef = null; // 清除之前创建的视图 this._updateView(); }

_updateView() 私有方法

// 更新视图 private _updateView() { // this._context.$implicit = this._context.ngIf = condition // 若condition表达式的值为truthy if (this._context.$implicit) { // 若_thenViewRef为null且_thenTemplateRef存在,则创建_thenViewRef内嵌视图 if (!this._thenViewRef) { this._viewContainer.clear(); this._elseViewRef = null; if (this._thenTemplateRef) { this._thenViewRef = this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context); } } } else { // condition表达式的值为falsy // 若_elseViewRef为null且_elseTemplateRef存在,则创建_elseViewRef内嵌视图 if (!this._elseViewRef) { this._viewContainer.clear(); this._thenViewRef = null; if (this._elseTemplateRef) { this._elseViewRef = this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context); } } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wysgdw.html