Angular2 template expression called twice for each component when changes are detected

Pretty standard situation.

There is one parent component <item-list>. Inside its template with *ngFor20 child components are created <item-block>. Styles of child components set with the directive [ngStyle]and template expression that calls the function setStyles().

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

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

Questions :

  • Why this happens and expected behavior.
  • How it affects performance.
  • How to avoid this is only one call per child component / discovery.

Example and plnkr :

plnkr (click an item - open a console to display debugging)

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'
      };
  }
}
+4
source share
2 answers
[ngStyle]="setStyles()"

calls setStylesfor a call every time a change is made (which can be quite common and can hurt performance). In addition, since it setStyles()returns every instance of the object each time, it must throw an exception. “Expression changed since last check” or similar.

.

:

[ngStyle]="myStyles"
+3

( ) Angular .
.

?

main.ts :

import { enableProdMode } from '@angular/core';
// ...
enableProdMode();
// ...
platformBrowserDynamic().bootstrapModule(AppModule)

.

0

Source: https://habr.com/ru/post/1665781/


All Articles