angular - 调用插值,即使 ChangeDetectionStrategy.OnPush

标签 angular performance

对于我的项目,我必须创建一个包含许多行 (> 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/

相关文章:

javascript - 如何在普通 ES5 (Javascript) 中向 Angular 组件注入(inject)自定义服务?

c# - Empty Infinite While 循环的 CPU 使用率增加

c# - .Net Remoting 与 WCF

javascript - 在 JavaScript 中比较字符串的最快方法是什么?

angular - 在 stackblitz Angular 项目上找不到文件

javascript - NGRX 处理获取/创建/删除错误

angular - 如何在 Angular 中使用 subscribe-next RxJS?

javascript - 如何在 Angular 4 项目中导入 bootstrap-daterangepicker?

mysql - 包括数据库在内的单元测试应用程序太慢

python读取文件,为每一行保存一个新列并保存相同的文件