Búsqueda de sitios web

angular - ¿Por qué la función ng-if se repite a sí misma?


Estoy pasando una función booleana en el atributo ngIf en lugar de una condición booleana en el archivo de plantilla HTML. Pero esa función booleana se repite según la cantidad de datos en la variable messages. Si messages tiene 2 objetos, entonces el valor de ctr en la consola aumenta de 1 a aproximadamente 69 en lugar de solo 1 o 2. ¿Cuál podría ser la razón de esto y cómo evitarlo al pasar la función en el atributo ngIf?

HTML

<ion-row *ngFor="let message of messages; let i = index; trackBy:trackByMsgId">
      <ion-badge *ngIf="isNewDate(i)" color="primary" class="ion-margin">{{message.time | date: 'longDate'}}</ion-badge>
</ion-row>

TS

let ctr = 0;
isNewDate(i) {
    this.ctr += 1;
    console.log('ctr: ', this.ctr);
    return true;
}

Respuesta #1

La función isNewDate() se llamará cada vez que Angular ejecute ChangeDetection según la ChangeDetectionStrategy, debido a que Angular no puede predecir si el valor de retorno de la función isNewDate() ha cambiado. Por lo tanto, necesita ejecutar la función cada vez que se ejecuta la detección de cambios.

Actualizar DOM es parte de ChangeDetection y la directiva ngFor actualizó el DOM, y ejecutará el ChangeDetection de Angular. Entonces, si tienes un arreglo con length 4 y ChangeDetection se ejecuta 4 veces por cada elemento, tu función se llamará 16 veces, pero la variable del componente ctr se reiniciará por cada elemento. Puedes ver un ejemplo aquí en Stackblitz. Así que, gracias por el útil comentario de @Adam y de acuerdo con el artículo mencionado:

Aunque las llamadas a funciones en las plantillas de Angular son muy convenientes y técnicamente válidas, pueden causar serios problemas de rendimiento.

Y por eso nunca deberías usar llamadas a funciones en las expresiones de plantillas de Angular. No es una buena práctica.

La solución para evitar llamadas a funciones:

  1. Usa pipes
  2. Calcule manualmente los valores y actualice algunas Variables en app.component.ts y úselas en la plantilla (app.component.html).