Angular2模板表达式在更改检测时对每个组件调用两次 [英] Angular2 template expression called twice for each component on change-detection

查看:83
本文介绍了Angular2模板表达式在更改检测时对每个组件调用两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

相当标准的情况.

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

There is one parent component <item-list>. Inside its template with *ngFor generated 20 child components <item-block>. Child component styles set with [ngStyle] directive and template expression that calls function setStyles().

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

The problem (or maybe not) is that when any event emitted on one specific child element, expression setStyles() executed twice for each of child components.

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

So if we click on one specific item in our example, and we have 20 <item-block> components - setStyles() will be executed 20+20 times.

问题是:

  1. 为什么会发生这种情况以及它是否是预期行为?
  2. 它如何影响性能
  3. 如何避免这种情况-每个子组件/检测更改仅调用一次.

示例& plnkr :

plnkr(单击项目-打开控制台以进行调试输出)

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()每次都返回不同的对象实例,因此它会导致异常. 自上次检查以来,表达已更改"或类似内容.

causes setStyles to be called every time change detection is run (which can be quite often and will hurt performance). Also because setStyles() returns a different object instance every time, it should cause an exception. "Expression changed since it was last checked" or similar.

不建议从这种方式从视图调用方法.

Calling methods from the view this way is discouraged.

相反,将值分配给属性并绑定到该属性:

Instead assign the value to a property and bind to that property:

[ngStyle]="myStyles"

这篇关于Angular2模板表达式在更改检测时对每个组件调用两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆