【发布时间】:2021-04-05 01:38:28
【问题描述】:
模板有一个输入监听 keyUp 事件。该组件有一个 Observable 和一个 Subject。 Subject 通过管道将字符串值从输入映射到 Stock[] Observable 的操作符。 在每个 keyUp 事件中,Subject 都会发出带有来自输入的新值的下一个事件。
模板:
<div>
<input name="searchBox"
[(ngModel)]="searchString"
placeholder="Search here"
(keyup)="search()">
</div>
<h2>
We have found {{ (stocks$ | async )?.length }} stocks!
</h2>
<app-stock-item *ngFor="let stock of stocks$ | async"
[stock]="stock"
>
</app-stock-item>
组件:
import { Component, OnInit } from '@angular/core';
import {Observable} from 'rxjs';
import {StockService} from '../../services/stock.service';
import {Stock} from '../../model/stock';
import {Subject} from 'rxjs';
import {debounceTime,switchMap,distinctUntilChanged,
startWith, share} from 'rxjs/operators';
@Component({
selector: 'app-stock-list',
templateUrl: './stock-list.component.html',
styleUrls: ['./stock-list.component.css']
})
export class StockListComponent implements OnInit {
public stocks$!: Observable<Stock[]>;
public searchString:string = "";
private searchTerms:Subject<string> = new Subject();
constructor(private stockService:StockService) { }
ngOnInit(): void {
console.log(this.stocks$);
// how does this work after ngOnInit is executed?
this.stocks$ = this.searchTerms.pipe(
startWith(this.searchString),
debounceTime(500),
distinctUntilChanged(),
//getStocks returns an Observable of HttpClient
switchMap( (query) => this.stockService.getStocks(query)),
share()
);
}
search(){
this.searchTerms.next(this.searchString);
}
}
如果每次渲染组件时只调用一次 ngOnInit,为什么在 ngOnInit 完成执行后 Subject.pipe() 和 Subject.next() 仍然有效?主题是否在代码中的任何位置被订阅?
【问题讨论】:
-
之所以有效,是因为您的模板中有两个
AsyncPipe用法。两者都隐式创建订阅。 -
@miqh 所以当订阅 Observable 时,Subject 也会被订阅?
-
我认为这些异步管道订阅了
stocks$observable。stocks$的定义恰好基于searchTerms主题。换句话说,异步管道不会创建对基础主题的直接订阅——在我看来这也没有意义,除非您在模板中有要显示当前searchTerms值的内容(即通过另一个异步管道)。 -
主题管道中的运算符是否保存在某个地方? ngOnInit 完成后如何不销毁操作符?
-
这是 observable 定义的一部分——仅仅因为执行离开
ngOnInit()并不意味着 observable 消失了。stocks$的范围是组件的生命周期。当组件被销毁时,异步管道订阅也会被销毁(如果您阅读了我上面链接的文档)。