Angular的搜索查询没有随着用户输入而更新

前端开发 2026-07-10

我在做一个针对动物园的Angular项目,练习使用RXJS。当用户进行搜索或输入按键时,先延时几毫秒再进行搜索,这样就不会在每次按键时都触发搜索。

然后再对已通过fetch获得的列表进行过滤。

不过我发现结果似乎滞后一个按键。

也就是说,例如有一个包含 { Leo, Lane, John } 的小名单。

我在搜索框中输入L 时,全部三个仍然显示。接着输入La(本应只显示Lane),结果Leo和 Lane都出现了(这和只输入L 时应该发生的行为不符)。

然后我输入Lan,只有Lane显示。

我想让搜索框在每次按键时就更新,不要滞后一个按键。

HTML:

  @for (animal of userAnimals; track animal) {
    <mat-card class="card" appearance="outlined" style="margin: 10px;">
      <mat-card-header>
        <img
          #animalIMG
          src="A-Cat.jpg"
          class="card-img-top animalImage"
          alt="..."
          [id]="animal.species"
          (load)="loadImage(animalIMG.id)"
          style="height: 200px"
        />
      </mat-card-header>
      <mat-card-title>{{ animal.name }} The {{ animal.species }}</mat-card-title>
      <mat-card-content>
        @if (animal.openStatus) {
          <p class="bg-success-subtle">{{ animal.name }} Is open</p>
        } @else {
          <p class="bg-warning-subtle">{{ animal.name }} Is Closed</p>
        }
      </mat-card-content>
    </mat-card>

grid-view.ts:

  searchSubjet$ = new Subject<string>();
  public animals: IAnimal[] = [];
  public userAnimals: IAnimal[] = [];
  public searchString!: string;
  // Inject the list of animals
  constructor(
    private animalListService: Animalslist,
    private notifyService: NotificationService,
    private cdr: ChangeDetectorRef,
  ) {
    afterNextRender(() => {
      this.notifyService.enableNotifications();
    });
  }

  public async ngAfterViewInit(): Promise<void> {
    this.searchSubjet$.pipe(debounceTime(500)).subscribe((userSearch) => {
      console.log(userSearch);
      if (userSearch === '' || userSearch === null) {
        this.userAnimals = this.animals;
      } else {
        this.userAnimals = this.animals.filter((a) =>
          a.name.toUpperCase().startsWith(userSearch.toUpperCase()),
        );
      }
      this.cdr.detectChanges();
    });
  }

  public async ngOnInit() {
    // Get the list of animals.
    // This list can be iterated over to make a proper grid view of animals.
    this.animals = await this.animalListService.getAll();
    this.userAnimals = this.animals;

    // https://stackoverflow.com/questions/34364880/expression-has-changed-after-it-was-checked
    // this.cdr.detectChanges();
  }



  public inputChanged($event: any) {
    this.searchSubjet$.next($event.srcElement.value);
  }

解决方案

通常你会使用RxJS的 debounce、FormControl和 asyncPipe

search=new FormControl()
animals$=search.valueChanges.pipe(
                   startsWith(null),
                   debounceTime(200),
                   map((search:string)=> {
                       return !x?this.animals:
                                 this.animals.filter(x=>a.name.toUpperCase()
                                          .startsWith(userSearch.toUpperCase())
                                  }))

并使用

<input [formControl]="search"/>
@for (animal of animals$|async; track animal) 
{
   ...
}

要使用signal,请查看 此链接

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章