У меня есть простая таблица, в которой я использую ngFor для отображения строк.
app.component.html
<table>
<thead>
<tr>
<th>Header 1</th>
</tr>
</thead>
<tbody>
<tr *ngFor = "let item of items">
<td>
<a>{{myFunc(item?.id) ? "1" : "2"}}</a>
</td>
</tr>
</tbody>
</table>
items - это список с одним объектом. Я ожидал, что myFunc() будет оценен как только один раз для одного объекта в списке items. Однако похоже, что myFunc() называется 4 раза, и я понятия не имею, почему.
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
items = [{"id": 1}];
myFunc(itemId) {
console.info("i was called");
return true;
}
}
Демо, показывающее эту ошибку: https://stackblitz.com/edit/angular-j7jgfl. «Мне звонили» выводится на консоль 4 раза. Может ли кто-нибудь сказать мне, почему и как правильно вызвать функцию один раз?
Возможный дубликат Почему выражение в моем app.component.html вызывается несколько раз?
Что говорит @DanielWStrimpel, или используйте каналы, поскольку они имеют функцию запоминания. Означает, что если ввод не меняет, канал об этом знает. На ngConf18 была блестящая презентация об оптимизации angular, я думаю, она доступна на youtube.
@DanielWStrimpel, что вы имеете в виду «всякий раз, когда данные, влияющие на результат, меняются»? Вы можете привести мне пример? В этом случае данные, которые влияют на результат, - это элемент, и он изменяется на каждой итерации цикла for.
Всякий раз, когда данные, которые зацикливаются, меняются, я запускал карту для каждого элемента и преобразовывал ее, чтобы добавить дополнительное свойство, которое было результатом этой проверки. Таким образом, операция выполняется только тогда, когда данные были изменены.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


В консоли вы можете увидеть следующее сообщение:
Angular is running in the development mode. Call enableProdMode() to enable the production mode.
Это означает, что Angular повторно запускает обнаружение изменений в режиме разработки после каждого цикла и проверяет, что ничего не изменилось после второго раза. Если это так, будет показано предупреждение, потому что эти изменения могут не быть обнаружены в производственной среде без повторного запуска.
Если вы запустите enableProdMode(); в файле main.ts перед загрузкой (вам нужно обновить один раз в Stackblitz), вы увидите, что функция будет вызываться вдвое реже, осталось два раза.
Обнаружение изменений будет запускаться по разным причинам при использовании ChangeDetectionStrategy по умолчанию. Каждый раз ваша функция будет оцениваться. Если вы хотите, чтобы обнаружение изменений запускалось только один раз, измените ChangeDetectionStrategy на OnPush следующим образом:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
changeDetection: ChangeDetectionStrategy.OnPush
})
Обнаружение изменений теперь запускается только при изменении значения @Input (ссылка на объект) или при возникновении события.
вот ваш улучшенный код, я не знаю, правильно я сделал или нет
<tr *ngFor = "let item of items">
<td>
<a>{{myFunc(item) ? "1" : "2"}}</a>
</td>
</tr>
myFunc(itemId) {
if (itemId){
console.info("i was called");
return true;
}else{
return false;
}
}
может это поможет тебе
Ваша функция (
myFunc) будет вызываться каждый раз при запуске цикла обнаружения изменений. Если вы не хотите, чтобы это выполнялось много раз, лучше всего выполнять обработку всякий раз, когда данные, влияющие на результат, изменяются, и сохранять это как переменную.