Angular - Почему моя простая функция вызывается много раз?

У меня есть простая таблица, в которой я использую 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 раза. Может ли кто-нибудь сказать мне, почему и как правильно вызвать функцию один раз?

Ваша функция (myFunc) будет вызываться каждый раз при запуске цикла обнаружения изменений. Если вы не хотите, чтобы это выполнялось много раз, лучше всего выполнять обработку всякий раз, когда данные, влияющие на результат, изменяются, и сохранять это как переменную.

Daniel W Strimpel 10.05.2018 01:11

Что говорит @DanielWStrimpel, или используйте каналы, поскольку они имеют функцию запоминания. Означает, что если ввод не меняет, канал об этом знает. На ngConf18 была блестящая презентация об оптимизации angular, я думаю, она доступна на youtube.

Felix Lemke 10.05.2018 01:30

@DanielWStrimpel, что вы имеете в виду «всякий раз, когда данные, влияющие на результат, меняются»? Вы можете привести мне пример? В этом случае данные, которые влияют на результат, - это элемент, и он изменяется на каждой итерации цикла for.

Warren Crasta 10.05.2018 04:00

Всякий раз, когда данные, которые зацикливаются, меняются, я запускал карту для каждого элемента и преобразовывал ее, чтобы добавить дополнительное свойство, которое было результатом этой проверки. Таким образом, операция выполняется только тогда, когда данные были изменены.

Daniel W Strimpel 10.05.2018 04:04
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
126
2

Ответы 2

В консоли вы можете увидеть следующее сообщение:

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;
}

  }

может это поможет тебе

Другие вопросы по теме