方法在 angular material 自动完成中被多次调用

method gets called multiple times in angular material autocomplete

我们使用Angular material自动完成创建了一个组件。为了显示选项,我们正在遍历一个包含 51 个对象的 数组 。我正在对已选择的选项应用 CSS class。 isAccountingTypeSelected 方法确定选项是否被选中。 该方法被调用 51*28 = 1428 次。我好像不太明白是什么原因?它应该只被调用 51 次,不是吗?

<mat-form-field class="full-width">
  <input type="text" matInput #autoCompleteInput [formControl]="autocompleteForm" [matAutocomplete]="auto" placeholder="Choose Accounting Type" aria-label="Number">

  <span matSuffix class="close-icon hover" *ngIf="autoCompleteInput.value" (click)="clearAll($event)"></span>
  <span matSuffix class="arrow-drop-down-icon hover" (click)="openPanel()"></span>

  <mat-autocomplete #auto="matAutocomplete" (optionSelected)="accountingTypeSelected($event)">
    <mat-option *ngFor="let accountingType of filteredAccountingTypes | async" [value]="accountingType.code">
      <span class="accounting-type-options" [class.selected]="isAccountingTypeSelected(accountingType.code)">
        {{ accountingType.name + ' (' + accountingType.code + ')' }}
      </span>
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

isAccountingTypeSelected(code: string): boolean {
  console.log('I was called');
  if (this.selectedAccountingTypes.find((accountingType: AccountingType) => accountingType.code === code)) {
    return true;
  }

  return false;
}

Angular 将在每次检查更改时评估该表达式,在您的情况下可能是 css 被添加到您的 span 元素中。 在 for 循环中从模板调用方法不是最好的方法,因为它们被调用得非常频繁。您应该将结果存储在 属性 中并改为绑定到此 属性。

绑定问题。 Angular 检查更多次结果值。你可以试试 ChangeDetectionStrategy.CheckOnce

Angular 多次使用 changedetection 生命周期来检查 [class.selected] 或 ngClass 的函数是否发生了变化。如果你使用函数,它会调用多次。因此,不建议在绑定时使用函数,相反,您应该计算 component.ts 文件中的值,并将这些值绑定到 ngClass 或 [class].

示例:Stackblitz

N.B:我们知道当我们更改选择的值时会触发事件更改,我们可以计算它并将计算结果附加到 [class.my-class] 或 ngClass .

您的 ngFor 循环需要跟踪一个特定的 ID,这样它就不会无缘无故地重新呈现。试试这个:

<mat-option *ngFor="let accountingType of filteredAccountingTypes | async; trackBy: trackByCode"[value]="accountingType.code">
</mat-option>

然后你添加这个函数:

trackByCode(index: number, accountingType: yourType): string {
    return accountingType.code;
}