Angular2 模板表达式在变更检测时为每个组件调用两次

标签 angular angular2-template angular2-components angular2-changedetection

非常标准的情况。

有一个父组件<item-list> . 在其模板内带有 *ngFor生成了 20 个子组件 <item-block> . 使用 [ngStyle] 设置的子组件样式调用函数的指令和模板表达式 setStyles() .

问题(或可能不是)是当任何事件在一个特定的子元素上发出时,表达式 setStyles()为每个子组件执行两次。

因此,如果我们在示例中单击一个特定项目,我们将有 20 <item-block>组件 - setStyles()会被执行20+20次。

问题是:

  1. 为什么会发生,这是预期的行为。
  2. 它如何影响性能
  3. 如何避免 - 每个子组件/检测更改只调用一次。

例子&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'
      };
  }
}

最佳答案

[ngStyle]="setStyles()"

导致每次运行更改检测时调用 setStyles(这可能会很频繁并且会影响性​​能)。也因为 setStyles() 每次都返回不同的对象实例,所以应该会引发异常。 “自上次检查以来表达式已更改”或类似内容。

不鼓励以这种方式从 View 中调用方法。

而是将值分配给属性并绑定(bind)到该属性:

[ngStyle]="myStyles"

关于Angular2 模板表达式在变更检测时为每个组件调用两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41471232/

相关文章:

angular - 如何从 Intellij idea 2017.1 运行 Angular 应用程序?

angular - 结构指令的上下文未更新

javascript - 当属性存在且为空时,使 Angular 2 组件输入 "true"

Angular 2 找不到在我的功能模块中声明的组件

angular - 在 Angular 2 中保留页面重新加载的数据

Angular 2 项目托管

Angular 4 - 用户界面路由器

angular - .detectChanges() 在 Angular 测试中不起作用

Angular 2 : Can't bind to 'ngModel' even though FormsModule is imported

angular - 使用 @Input 装饰器访问传递的数据