对于我的项目,我必须创建一个包含许多行 (> 1000) 的表,但效果不佳。为了演示这个问题,我创建了一个简单的应用程序,其中包含一个可折叠 div 和多个 div,它们是通过 *ngFor 创建的。
只有一个组件(由 Angular 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>
组件类创建 100 个具有名为 name 的属性的对象。模板中调用的方法 getName 将调用记录到控制台并返回 name 属性。
该类还提供了用于展开/折叠可折叠 div 的方法。
当我单击 TEST-div 时,将执行方法toggleDiv()。并且:每次调用此方法时,都会调用所有行的 getName() 方法。
恕我直言,这是完全没有必要的,并且会产生性能问题(使用 css 动画等)。
由于该组件使用 ChangeDetectionStrategy.OnPush,我不明白为什么 Angular 会执行所有这些插值,即使没有任何变化!
有人知道如何改变这种行为吗?我希望有 Angular 地渲染表格,并且除非组件的任何输入参数发生变化,否则绝对不执行任何操作。
尝试过的 Angular 版本: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] 中找到
最佳答案
不要绑定(bind)到函数,而是绑定(bind)到属性
{{getName(row)}}
应该是
{{getName[row]}}
其中 getName
是一个数组字段,其中包含每行的预先计算值。
@Input()
更新或组件中的事件处理程序收到事件 ((click)=". ..")
或当 |async
管道接收到事件时。
OnPush
只是在父组件运行更改检测时跳过组件的更改检测。
您还可以分离当前组件的更改检测器,以避免比 OnPush 本身更严格的更改检测。
关于angular - 调用插值,即使 ChangeDetectionStrategy.OnPush,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48092556/