很标准的情况 .
有一个父组件 <item-list>
. 在其模板内部 *ngFor
生成了20个子组件 <item-block>
. 使用 [ngStyle]
指令设置的子组件样式和调用函数 setStyles()
的模板表达式 .
问题(或可能不是)是当在一个特定子元素上发出任何事件时,表达式 setStyles()
为每个子组件执行两次 .
因此,如果我们点击示例中的一个特定项目,并且我们有20个 <item-block>
组件 - setStyles()
将执行20次20次 .
The questions are :
-
为什么会发生这种情况并且是预期的行为 .
-
它如何影响性能
-
如何避免 - 每个子组件/检测更改只能调用一次 .
Example & plnkr :
plnkr (click on item - open console for debug output)
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'
};
}
}
2 回答
每次运行更改检测时都会调用
setStyles
(这可能经常会影响性能) . 另外因为setStyles()
每次都返回一个不同的对象实例,所以它应该导致异常 . "Expression changed since it was last checked"或类似的 .不鼓励以这种方式从视图中调用方法 .
而是将值分配给属性并绑定到该属性:
默认情况下( development mode )角运行检测更改机制 twice .
在 production mode 中,它减少到 single change .
如何将Detect Changes机制切换为 生产环境 ?
在
main.ts
文件中尝试添加:并重新加载应用程序 .