在我看来,这个用于执行插入到输入标签中的术语的动态搜索的 Angular 管道是如何工作的?

Posted

技术标签:

【中文标题】在我看来,这个用于执行插入到输入标签中的术语的动态搜索的 Angular 管道是如何工作的?【英文标题】:How is it working this Angular pipe used to perform a dynamic search of terms inserted into an input tag in my view? 【发布时间】:2019-04-11 21:28:44 【问题描述】:

我是 Angular 的新手,我正在关注这个官方 Angular 教程:https://angular.io/tutorial/toh-pt6

我对它的工作原理有些怀疑,这是我对 HeroSearchComponent 类的注释代码:

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 

  // It is an Observable emitting an array of Hero objects:
  heroes$: Observable<Hero[]>;

  /**
   * The searchTerms property is declared as an RxJS Subject.
   * 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.
   */
  private searchTerms = new Subject<string>();

  constructor(private heroService: HeroService) 

  /**
   * Push a search term into the observable stream.
   * Every time the user types in the textbox, the binding calls search() with the textbox value, a "search term". 
   * The searchTerms becomes an Observable emitting a steady stream of search terms. 
   */ 
  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)),
    );
  

该类用于从hero-search.component.html中搜索英雄,包含:

<div id="search-component">
  <h4>Hero Search</h4>

  <!--
    As the user types in the search box, a keyup event binding calls 
    the component's search() method with the new search box value
  -->
  <input #searchBox id="search-box" (keyup)="search(searchBox.value)" />

  <ul class="search-result">
    <!--
        The *ngFor iterates over a list called heroes$, not heroes.
        The $ is a convention that indicates heroes$ is an Observable, not an array.
        The *ngFor can't do anything with an Observable. 
        But there's also a pipe character (|) followed by async, which identifies Angular's AsyncPipe.
        The AsyncPipe subscribes to an Observable automatically so you 
        won't have to do so in the component class.
    -->
    <li *ngFor="let hero of heroes$ | async" >
      <a routerLink="/detail/hero.id">
        hero.name
      </a>
    </li>
  </ul>
</div>

这是我的解释,我绝对不确定它是否正确。

HeroSearchComponentheroes$ 字段不是数组,而是发出数组的 Observable。这是因为我们生活在一个异步的世界中,所以我们必须等待服务器提供响应。

在视图中我不能直接迭代一个数组,但我必须等待我收到响应(当前面的 Observable 发出 Hero 的数组时),这是使用 asyncornous 在此事件上注册的管道:

<li *ngFor="let hero of heroes$ | async" >

这应该是正确的......

然后进入我的视图:

<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />

当用户在输入标签中插入一个新字符时,它被称为组件 search() 方法,传递插入到输入标签中的值(“a”、“ab”、“abc” 、“ab”等)。

这是 search() 方法:

search(term: string): void 
  this.searchTerms.next(term);

查看它并不是直接执行调用后端服务的搜索,而是将接收到的新词推送到 searchTerms

这个searchTerms 对象是一个Subject。据我了解,Subject 是一个可以发出事件(作为 Observable**)同时可以接收事件流的对象(在这种情况下,每次都是术语流)用户在视图搜索输入中插​​入一个新字符)。

但是...如何以及在何处执行调用以获取与插入术语匹配的英雄列表?

我的想法是这样的:它不是直接在这个方法中做的,而是有一种预先设定的行为。当这个类被 ngOnInit() 方法实例化时,这是完成的:

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)),
  );

这基本上是这样说的:调用 heroService.searchHeroes(term) 方法(在我的后端执行搜索的方法)每次传递 term searchTerms 接收\发出事件(即要搜索的最后一个词)。理论上,该管道设置为不是针对每个插入的字符而是每 300 毫秒执行一次,以避免执行太多调用)。

我不确定这种机制以及该管道的工作原理。

正确完整的解释是什么?

【问题讨论】:

到目前为止,您的所有解释都是正确的。提到的管道 (| async) 订阅给定的 observable 并从 observable 返回给定的值。另一种可能性(或者更好的是异步管道在后台执行的操作)是调用 observable 的 subscribe 方法。两种方法之间的差异可以是read here。如果您需要有关订阅本身的更多信息take a look here 【参考方案1】:

What is pipe() function in Angular 2?

Angular 中有管道概念,RxJS 中有管道()函数

1) Angular 中的管道:管道将数据作为输入并将其转换为所需的输出 https://angular.io/guide/pipes

2) RxJS 中的 pipe() 函数:您可以使用管道将运算符链接在一起。管道让您可以将多个函数组合成一个函数。

pipe() 函数将要组合的函数作为其参数,并返回一个新函数,该函数在执行时会按顺序运行组合函数。 https://angular.io/guide/rx-library(在这个网址搜索管道,可以找到相同的)

【讨论】:

以上是关于在我看来,这个用于执行插入到输入标签中的术语的动态搜索的 Angular 管道是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

wp_localize_script 用于插入图像

将图像插入 .docx 文件

如何在列表和标签中插入动态 SQL?

Angular2动态插入脚本标签

将标签和图像动态添加到 Android 中的自定义视图

include指令和动作的区别