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 "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 "htmlcode">// 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); } } } }
ngIf
指令的源码相对比较简单,最核心的是_updateView()
方法。而该方法中最重要的功能就是如何基于模板对象创建内嵌视图。接下来我们来分析一下ViewContainerRef
对象的createEmbeddedView()
方法。ViewContainerRef - createEmbeddedView()
方法签名
// angular\packages\core\src\linker\view_container_ref.ts export abstract class ViewContainerRef { /** * 基于TemplateRef对象创建Embedded View(内嵌视图),然后根据`index`指定的值,插入到容器中。 * 如果没有指定`index`的值,新创建的视图将作为容器中的最后一个视图插入。 */ abstract createEmbeddedView<C>( templateRef: TemplateRef<C>, context"htmlcode">// angular\packages\core\src\view\refs.ts class ViewContainerRef_ implements ViewContainerData { // ... createEmbeddedView<C>( templateRef: TemplateRef<C>, context"htmlcode">// angular\packages\core\src\linker\template_ref.ts export abstract class TemplateRef<C> { abstract createEmbeddedView(context: C): EmbeddedViewRef<C>; }方法实现
// angular\packages\core\src\view\refs.ts class TemplateRef_ extends TemplateRef<any> implements TemplateData { // ... createEmbeddedView(context: any): EmbeddedViewRef<any> { return new ViewRef_(Services.createEmbeddedView( this._parentView, this._def, this._def.element !.template !, context)); } } export interface TemplateData extends TemplateRef<any> { _projectedViews: ViewData[]; }看完上面的源码,毫无疑问接下来我们要继续分析
Services
对象中的createEmbeddedView()
方法。Services - createEmbeddedView()
Services 对象定义
// angular\packages\core\src\view\types.ts export const Services: Services = { setCurrentNode: undefined !, createRootView: undefined !, createEmbeddedView: undefined !, createComponentView: undefined !, createNgModuleRef: undefined !, overrideProvider: undefined !, clearProviderOverrides: undefined !, checkAndUpdateView: undefined !, checkNoChangesView: undefined !, destroyView: undefined !, resolveDep: undefined !, createDebugContext: undefined !, handleEvent: undefined !, updateDirectives: undefined !, updateRenderer: undefined !, dirtyParentQueries: undefined !, };Services 对象初始化
// angular\packages\core\src\view\services.ts export function initServicesIfNeeded() { if (initialized) { return; } initialized = true; const services = isDevMode() "htmlcode">function createProdServices() { return { setCurrentNode: () => {}, createRootView: createProdRootView, createEmbeddedView: createEmbeddedView // 省略了其它方法 }createEmbeddedView() 方法
// angular\packages\core\src\view\view.ts export function createEmbeddedView( parent: ViewData, anchorDef: NodeDef, viewDef: ViewDefinition, context"htmlcode">ViewContainerRef_ -> createEmbeddedView() => TemplateRef_ -> createEmbeddedView() => Services -> createEmbeddedView() => Call createEmbeddedView()以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!暂无评论...
更新日志
2024年11月25日
2024年11月25日
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]