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

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

问题描述

非常标准的情况.

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

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

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

问题是:

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

示例和plnkr:

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

从 '@angular/core' 导入 {Component}@成分({选择器:'项目列表',模板:`<项目块[项目]="项目"*ngFor="让项目的项目"></item-block>`,})导出类 ItemListComponent {项目:任何[] = [];构造函数(){}ngOnInit() {//生成虚拟空项for (让 i = 0; i <20; i++) {this.items.push({值:'项目#' + i;})}}}从@angular/core"导入 {Component, Input}@成分({选择器:'项目块',模板:`

解决方案

[ngStyle]="setStyles()"

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

不鼓励以这种方式从视图调用方法.

改为将值分配给属性并绑定到该属性:

[ngStyle]="myStyles"

Pretty standard situation.

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().

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.

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.

The questions are:

  1. Why its happening and is it expected behavior.
  2. How it affect performance
  3. How it could be avoided - only one call per child component/detection change.

Example & 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()"

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天全站免登陆