问题描述
相当标准的情况.
有一个父组件<item-list>
.在带有*ngFor
的模板内部,生成了20个子组件<item-block>
.通过[ngStyle]
指令和调用函数setStyles()
的模板表达式设置的子组件样式.
There is one parent component <item-list>
.Inside its template with *ngFor
generated 20 child components <item-block>
.Child component styles set with [ngStyle]
directive and template expression that calls function setStyles()
.
问题(或可能不是问题)是,当在一个特定的子元素上发出任何事件时,表达式setStyles()
对每个子组件执行两次.
The problem (or maybe not) is that when any event emitted on one specific child element, expression setStyles()
executed twice for each of child components.
因此,如果我们在示例中单击一个特定项目,则有20个<item-block>
组件-setStyles()
将被执行20 + 20次.
So if we click on one specific item in our example, and we have 20 <item-block>
components - setStyles()
will be executed 20+20 times.
问题是:
- 为什么会发生这种情况以及它是否是预期行为?
- 它如何影响性能
- 如何避免这种情况-每个子组件/检测更改仅调用一次.
示例& plnkr :
import {Component} from '@angular/core'
@Component({
selector: 'item-list',
template: `
<item-block
[item]="item"
*ngFor="let item of items"
></item-block>
`,
})
export class ItemListComponent {
items: any[] = [];
constructor() {}
ngOnInit() {
// generate dummy empty items
for (let i = 0; i < 20; i++) {
this.items.push(
{
value: 'item #' + i;
}
)
}
}
}
import {Component, Input} from '@angular/core'
@Component({
selector: 'item-block',
template: `
<div
class="item"
[ngStyle]="setStyles()"
(click)="testClick($event)"
>{{item.value}}</div>
`,
})
export class ItemBlockComponent {
@Input() item: any;
constructor() {}
testClick(): void{
console.log('item clicked');
}
setStyles(){
console.log('seting styles...');
return {
'background': '#ccc'
};
}
}
推荐答案
[ngStyle]="setStyles()"
导致每次运行更改检测时都会调用setStyles
(这可能很常见,并且会损害性能).同样,由于setStyles()
每次都返回不同的对象实例,因此它会导致异常. 自上次检查以来,表达已更改"或类似内容.
causes setStyles
to be called every time change detection is run (which can be quite often and will hurt performance). Also because setStyles()
returns a different object instance every time, it should cause an exception. "Expression changed since it was last checked" or similar.
不建议从这种方式从视图调用方法.
Calling methods from the view this way is discouraged.
相反,将值分配给属性并绑定到该属性:
Instead assign the value to a property and bind to that property:
[ngStyle]="myStyles"
这篇关于Angular2模板表达式在更改检测时对每个组件调用两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!