Angular Performance: DOM Event causes unnecessary

2020-02-13 04:34发布

问题:

I have a simple page with an input element that has a DOM event (input). The HTML page also calls a function that just outputs something via console.log. Now when I open the page, it will show the log, but when I type something into the input field, it will also trigger the function EVERY time I type something.. (Actually, when I type a letter, it will console.logs TWICE every time)

Why does this happen? How to prevent it? I read some things about changeDetection, but is there another solution?

HTML:

{{test()}}

<input class="input-msg" [value]="textValue" (input)="textValue = $event.target.value;">

.ts:

export class TestComponent implements OnInit {

  constructor() { 
  }

  test() {
    console.log('test message');
  }
}

Expected Behavior:

The {{test()}} should not be called when typing something into the input field

回答1:

Since you're calling a function in one of the data-binding syntaxes, whenever Angular performs Change Detection, it will call this method.

Before for a function, anything that cases is the value that it returns. And for Angular to know that the returned value has changed, Angular will have to run it.

This is the exact same issue that people have raised a several questions here:

  1. Angular: Prevent DomSanizer from updating on DOM Events

  2. Angular performance: ngStyle recalculates on each click on random input

  3. Angular 7 ,Reactive Form slow response when has large data

You might want to read through these threads to understand what's going on here and how you can fix this issue.


The solution is to basically design your implementation in such a way, that it never calls a method in one of the data-binding syntaxes, i.e.

  1. In String Interpolation - {{ methodCall() }}
  2. In Property Binding - [propertyName]="methodCall()"
  3. In Attribute Binding - [class.className]="methodCall()" / [style.style-name]="methodCall()"

An alternative solution is do move this code to a Child Component and configure the changeDetectionStrategy on that child component to ChangeDetectionStrategy.OnPush