You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Material Autocomplete方法调用次数异常问题咨询

Why is isAccountingTypeSelected called 1428 times instead of 51 times in Angular Material Autocomplete?

Hey there! Let's break down why your method is getting called way more often than you expected, and how to fix it.

The Root Cause

This happens because of two key factors: Angular's change detection system and the internal behavior of Angular Material's Autocomplete component:

  1. Angular's Change Detection Cycle
    Angular re-evaluates every expression in your template during every change detection cycle. Since you're calling isAccountingTypeSelected(code) directly in the [class.selected] binding, this method runs once per list item every time change detection triggers.

  2. Autocomplete's Frequent State Changes
    The MatAutocomplete component triggers change detection multiple times during its lifecycle:

    • When the async pipe emits new values from filteredAccountingTypes
    • When the autocomplete panel opens/closes
    • When the input field is updated (even if filtering doesn't change the list)
    • When selectedAccountingTypes is modified
    • Even small UI interactions like hovering or scrolling can trigger cycles

With 51 list items and 28 change detection cycles, you end up with 51×28=1428 method calls.

Fixes to Reduce Unnecessary Calls

1. Precompute Selected States (Best Practice)

Instead of calling a method in the template, pre-calculate the selected status for each item when your data loads. This way, you're just referencing a property in the template, not running a function every cycle.

Update your component code:

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

// Add a new observable that includes selected status
filteredAccountingTypesWithSelection$: Observable<(AccountingType & { isSelected: boolean })[]>;

ngOnInit() {
  this.filteredAccountingTypesWithSelection$ = this.filteredAccountingTypes.pipe(
    map(accountingTypes => 
      accountingTypes.map(type => ({
        ...type,
        isSelected: this.selectedAccountingTypes.some(at => at.code === type.code)
      }))
    )
  );
}

Then update your template:

<mat-option *ngFor="let accountingType of filteredAccountingTypesWithSelection$ | async" [value]="accountingType.code">
  <span class="accounting-type-options" [class.selected]="accountingType.isSelected">
    {{ accountingType.name + ' (' + accountingType.code + ')' }}
  </span>
</mat-option>

2. Use OnPush Change Detection

Limit when change detection runs for your component by setting ChangeDetectionStrategy.OnPush. This tells Angular only to run change detection when input properties change or internal events are triggered.

Add this to your component decorator:

import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'your-component-selector',
  templateUrl: './your-component.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class YourComponent {
  // ... rest of your code
}

3. Cache Results (Quick Fix)

If you need to keep the method call in the template, cache the selected codes to avoid re-running the find operation every time:

private selectedCodes = new Set<string>();

ngOnInit() {
  this.updateSelectedCodes();
  // If selectedAccountingTypes changes dynamically, call updateSelectedCodes() whenever it updates
}

private updateSelectedCodes() {
  this.selectedCodes.clear();
  this.selectedAccountingTypes.forEach(at => this.selectedCodes.add(at.code));
}

isAccountingTypeSelected(code: string): boolean {
  return this.selectedCodes.has(code);
}

This turns the expensive find operation into a fast Set lookup, even if the method is called multiple times.

内容的提问来源于stack exchange,提问作者Pritam Bohra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:28:02