对于我的项目,我必须创建一个包含许多行(> 1000)的表,但这些表并不能很好地运行。为了演示这个问题,我创建了一个简单的应用程序,它包含一个可折叠的div和多个div,它们是通过* ngFor创建的。
只有一个组件(由角度CLI生成的app.component)。
html文件如下所示:
<div style="border:1px solid silver" (click)="toggleDiv()">TEST</div>
<div #divToToggle [ngStyle]="divStyle">
</div>
<div *ngFor="let row of rows">{{getName(row)}}</div>
Component-Class使用名为name的属性创建100个对象。模板中调用的方法getName将调用记录到控制台并返回name属性。
该类还提供了一种用于展开/折叠可折叠div的方法。
当我点击TEST-div时,执行toggleDiv()方法。并且:每次调用此方法时,都会调用所有行的方法getName()。
恕我直言,这是完全不必要的,并且会产生性能问题(使用css-animations等)。
由于组件使用ChangeDetectionStrategy.OnPush,我不明白,为什么angular会执行所有这些插值,即使没有任何变化!
有人有想法,如何改变这种行为?除非组件的任何输入参数发生变化,否则我希望使用angular来渲染表,而不是做任何事情。
尝试了Angular-Versions:4.4.4和5.1.3
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
rows: any[];
expanded = false;
divStyle: any;
expandedStyle = {
"height": "200px",
"background-color": "orange"
}
collapsedStyle = {
"display": "none"
}
constructor() {
this.divStyle = this.expandedStyle;
this.expanded = true;
this.rows = this.createRows(100);
}
toggleDiv() {
this.expanded = !this.expanded;
if (this.expanded) {
this.divStyle = this.expandedStyle;
} else {
this.divStyle = this.collapsedStyle;
}
}
getName(row:any): string {
console.log("getName called")
return row.name;
}
private createRows(count:number): any[] {
let rows: any[] = [];
for (let i=0; i < count; i++) {
rows.push({
name: "TEST " + (i+1)
})
}
return rows;
}
}
angular-CLI项目可以在[DropBox] [1]
找到答案 0 :(得分:2)
不要绑定到函数,而是绑定到属性
{{getName[row]}}
应该是
getName
其中OnPush
是一个数组字段,其中包含每行的预先计算的值。
@Input()
更新或组件中的事件处理程序收到事件((click)="...")
或|async
管道收到事件时, OnPush
会运行更改检测。
OnPush
只是在父组件运行更改检测时跳过组件的更改检测。
您还可以分离当前组件的更改检测器,以避免更严格地检查{{1}}本身的更改检测。