乐趣区

关于前端:Angular使用技巧NgIf-非常规用法

NgIf 是 angular 中应用频率十分高的指令,它的作用简略点说就是叛定一个表达式,并依据叛定后果匹配相应模板。

根本用法

<div *ngIf="condition; then thenBlock else elseBlock"></div>
<ng-template #thenBlock>Content to render when condition is true.</ng-template>
<ng-template #elseBlock>Content to render when condition is false.</ng-template>

以上语法能够艰深的了解为当表达式 condition 叛定为 true 时,应用 thenBlock 模板内容,否则应用 elseBlock 模板内容。这是 NgIf 用法的一种,它还有其它一些更为简洁的用法,具体可见 NgIf API。API 中对一些惯例用法曾经介绍的很具体了,根底的用法去看看文档就行了。

 

明天咱们次要来说个 NgIf 不太惯例的用法。

模板中长期变量

在 angular 组件模板中,有时候咱们可能会须要定义一个长期变量来晋升性能,比方像上面这个组件:

HTML

<div *ngFor="let item of items || []">
    <span [title]="getDisplayText(item)">{{getDisplayText(item) }}</span>
</div>

TS

@Component({
    selector: 'list',
    //...
})
export class ListComponent {@Input()
    items: Array<any>;

    @Input()
    displayMember: string;

    getDisplayText(item: any): any {return this.displayMember ? (item && item[this.displayMember]) : item;
    }
    
}

这是一个简略的列表组件,它绑定一个数组,并通过指定的 displayMember 来设置列表项要显示的文本内容。在组件模板 html 中,应用 span 标签包裹每项要显示的文本,并设置其 title 与显示文本雷同。因为显示文本能够动静设置 (displayMember),所以咱们将相干逻辑放在getDisplayText 办法中解决。

仔细一点就会留神到,咱们 html 模板中为了 2 处 (标签包裹的内容及 title) 文本显示,调用了 2 次 getDisplayText,但其实 2 次调用是反复的。这种问题如果在 js 代码里,定义一个长期变量问题就解决了,然而在 angular 的组件模板中并没有给咱们提供 定义长期变量 的指令,这时候咱们明天的配角 NgIf 就出场了。

NgIf多种用法中有一种是上面这样:

NgIf 其中一种用法

<div *ngIf="condition as value">{{value}}</div>

这句 condition as value 它能够将一个表达式 as 到一个变量,并且这个变量在其作用域 (节点) 范畴内均无效,这相当于变相的为咱们提供了在模板中定义长期变量的能力。

更新后的 HTML

<div *ngFor="let item of items || []">
    <span *ngIf="getDisplayText(item) as text" [title]="text">{{text}}</span>
</div>

当初咱们通过这个变相的长期变量,将原有须要调用 2 次的办法缩小到了仅调用 1 次,缩小了不必要的性能损失,这在更为简单的场景中会更加显著。
然而还不能快乐的太早,这里有一个问题,NgIf不论如何应用归根结底它还是会遵循本人的准则,就是叛定表达式,所以问题就是当 getDisplayText(item) 返回后果叛定为 false 时,相应的 span 节点并不会生成。如 items 其中一项为 null0时,null0 转换为 boolean 值均叛定为 false,所以节点并不会生成,无奈达到咱们显示字符串"0" 的预期。

解决办法其实很简略,咱们能够将返回后果封装成对象,因为对象叛定后果将始终为true

再次更新后的 HTML

<div *ngFor="let item of items || []">
    <span *ngIf="{text: getDisplayText(item) } as temp" [title]="temp.text">{{temp.text}}</span>
</div>

至此咱们就有了一个绝对完满的模板长期变量。

 

扩大

不仅仅是变相的模板长期变量,扩大一下它还能够做更多事,比方有时候咱们可能会须要在模板的某个节点生成的时候做点什么,它能够为咱们提供一个代码交互机会。

咱们给下面的组件加个数据项绑定事件,将相应定制性能公开给组件使用者。

HTML

<div *ngFor="let item of items || []; let index=index;">
    <span *ngIf="getBindingContext(item, index) as ctx" [title]="ctx.text" [style.color]="ctx.textColor">{{ctx.text}}</span>
</div>

TS

@Component({
    selector: 'list',
    //...
})
export class ListComponent {@Input()
    items: Array<any>;

    @Input()
    displayMember: string;

    getDisplayText(item: any): any {return this.displayMember ? (item && item[this.displayMember]) : item;
    }
    
    
    // 退出绑定事件
    @Output()
    itemBinding = new EventEmitter<{item: any, index: number, textColor?: string}>();

    getBindingContext(item: any, index: number): {text: string, textColor?: string} {let args: { item: any, index: number, textColor?: string} = {item, index};
        this.itemBinding.emit(args);
        return ({text: this.getDisplayText(item), textColor: args.textColor });
    }
    
}

当初组件使用者能够通过订阅 itemBinding 事件来定制每项的文本显示色彩了。

应用 1

<list [items]="[{firstName:'zhang', lastName:'san'}, {firstName:'li', lastName:'si'}]" displayMember="lastName"
    (itemBinding)="$event.textColor=$event.item.firstName ==='li'?'red': null">
</list>

应用 2

<list [items]="[0,1,2,3,4,5,6,7]" (itemBinding)="$event.textColor=$event.index%3 === 0 ?'red': null">
</list>

 

退出移动版