我正忙于MeteorJS和RxJS,它们正在退出,但有时也有点令人困惑。我目前的问题只是一个Angular NgRx问题,与MeteorJS无关。
正如您在示例中看到的,有一个基于showChannels
的ngIf
。此布尔值设置为false
。但是,内部的async for循环被引用到了我的store.select。但是,由于ngIf,管道中的运算符永远不会执行。这似乎陷入僵局。如何使订阅开始工作?
当我进行搜索时,它会将Channels添加到存储中,如果ngFor
循环周围没有ngIf
,那么store.select
就会工作。
当我将if重新放置到*ngIf="(channels$ | async) ?.length !== 0"
时,它会起作用,但当我进行一次搜索时,tap
会运行两次。
带订阅的带注释的store.select实际上在使用markForCheck
时工作得很好。关于不使用subscribe
时的最佳解决方案,有什么建议吗?
@Component({
selector: 'podcast-search',
changeDetection: ChangeDetectionStrategy.OnPush, // turn this off if you want everything handled by NGRX. No watches. NgModel wont work
template: `
<h1>Podcasts Search</h1>
<div>
<input name="searchValue" type="text" [(ngModel)]="searchValue" ><button type="submit" (click)="doSearch()">Search</button>
</div>
<hr>
<div *ngIf="showChannels">
<h2>Found the following channels</h2>
<div *ngFor="let channel of channels$ | async" (click)="loadChannel( channel )">{{channel.trackName}}</div>
</div>
`,
})
export class PodcastSearchComponent implements OnInit, OnDestroy {
channels$: Observable<Channel[]>;
searchValue: string;
showChannels = false;
constructor(
private store: Store<fromStore.PodcastsState>,
) {}
ngOnInit() {
this.channels$ = this.store.select(fromStore.getAllChannels).pipe(
filter(channels => !!channels.length),
// channels.length should always be truthy at this point
tap(channels => {
console.log('channels', !!channels.length, channels);
this.showChannels = !!channels.length;
}),
);
// this.store.select( fromStore.getAllChannels ).subscribe( channels =>{
// console.log('channels', !!channels.length, channels);
// this.channels$ = of ( channels );
// this.showChannels = !!channels.length;
// this.ref.markForCheck();
// } );
}
doSearch() {
console.log( 'search', this.searchValue );
this.store.dispatch( new fromStore.LoadChannels( this.searchValue ) );
}
使用ngIf
as
语法
*ngIf="channels$ | async as channels"
如果您有多个订阅并且它们没有嵌套,您也可以使用share
或shareReplay(1)
。如果所有订阅都同时完成,请使用share
,否则应使用shareReplay(1)
。