天天看點

給Angular應用增添搜尋Search功能

(1) dashboard Component裡增添搜尋Component的selector:

給Angular應用增添搜尋Search功能
使用指令行建立hero search Component:

ng generate component hero-search
給Angular應用增添搜尋Search功能
(2) 實作這個search Component的ui:
給Angular應用增添搜尋Search功能
<div id="search-component">
    <h4><label for="search-box">Hero Search</label></h4>
  
    <input #searchBox id="search-box" (input)="search(searchBox.value)" />
  
    <ul class="search-result">
      <li *ngFor="let hero of heroes$ | async" >
        <a routerLink="/detail/{{hero.id}}">
          {{hero.name}}
        </a>
      </li>
    </ul>
  </div>      

注意第七行:

Notice that the *ngFor iterates over a list called heroes$, not heroes. The $ is a convention that indicates heroes$ is an Observable, not an array.

這裡的heroes$不是一個數組,而是一個Observable.

Since *ngFor can’t do anything with an Observable, use the pipe character (|) followed by async. This identifies Angular’s AsyncPipe and subscribes to an Observable automatically so you won’t have to do so in the component class.

因為指令*ngFor不能直接同Observable打交道,是以使用管道| 和AsyncPipe.

(3) 實作search Component:

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

import { Observable, Subject } from 'rxjs';

import {
   debounceTime, distinctUntilChanged, switchMap
 } from 'rxjs/operators';

import { Hero } from '../hero';
import { HeroService } from '../hero.service';

@Component({
  selector: 'app-hero-search',
  templateUrl: './hero-search.component.html',
  styleUrls: [ './hero-search.component.css' ]
})
export class HeroSearchComponent implements OnInit {
  heroes$: Observable<Hero[]>;
  private searchTerms = new Subject<string>();

  constructor(private heroService: HeroService) {}

  // Push a search term into the observable stream.
  search(term: string): void {
    this.searchTerms.next(term);
  }

  ngOnInit(): void {
    this.heroes$ = this.searchTerms.pipe(
      // wait 300ms after each keystroke before considering the term
      debounceTime(300),

      // ignore new term if same as previous term
      distinctUntilChanged(),

      // switch to new search observable each time the term changes
      switchMap((term: string) => this.heroService.searchHeroes(term)),
    );
  }
}      

要點分析:

第19行的searchTerms來自庫rxjs的Subject對象:

給Angular應用增添搜尋Search功能

A Subject is both a source of observable values and an Observable itself. You can subscribe to a Subject as you would any Observable.

You can also push values into that Observable by calling its next(value) method as the search() method does.

将使用者輸入的term字元串變量放入searchTerms這個observable stream中。

給Angular應用增添搜尋Search功能

如果每次使用者輸入的input事件都導緻search函數執行的話,将會産生大量的HTTP請求,是以此處引入一個限流機制:

給Angular應用增添搜尋Search功能

debounceTime(300): waits until the flow of new string events pauses for 300 milliseconds before passing along the latest string. You’ll never make requests more frequently than 300ms. 新的input事件在300毫秒之後才會觸發。

distinctUntilChanged():ensures that a request is sent only if the filter text changed - 隻有當輸入發生變化時才觸發事件

switchMap() calls the search service for each search term that makes it through debounce() and distinctUntilChanged(). It cancels and discards previous search observables, returning only the latest search service observable.

取消和丢棄之前生成的observable,而使用目前最新的observable進行搜尋。

實作效果:點選搜尋結果:

給Angular應用增添搜尋Search功能
給Angular應用增添搜尋Search功能

繼續閱讀