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()
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件!
如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
白云城资源网 Copyright www.dyhadc.com
暂无“详解Angular 4.x NgIf 的用法”评论...
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]