Angular:如何在订阅模板之前通过管道传输 Observable
Angular: How to pipe Observable before subscribing in template
免责声明:这与 问题密切相关。
目前我有两个组件,Parent
和 Child
。
Parent
将一个 Observable 传递给 Child
,它在模板中订阅了这个 Observable 以避免 lifecycle/memory 泄漏问题。但是我必须 pipe
Child
组件中的 Observable 来设置一些东西。
parent.ts:
public $obs = Observable<any>;
....
loadData() {
this.obs$ = this.myService.getData();
}
parent.html:
<child [data$]="obs$"></child>
child.ts:
@Input() data$ : Observable<any>;
ngOnChanges(changes) {
if(changes.data$) {
console.log("changes detected");
this.data$.pipe(tap(data => console.log("tap worked")));
}
}
child.html
<div *ngIf="data$ | async as data;">
{{ data || json }}
</div>
数据存在于模板中,控制台日志显示已检测到更改,但从未显示“tap worked”,这让我怀疑我对 pipe
的调用可能也来了晚的。
有什么方法可以在模板“调用”订阅之前进行管道传输吗?
想法是让许多组件与 child 类似,都对数据做不同的事情 object。我考虑过订阅 Parent
中的服务并将 json 值直接传递给所有 child,但这需要我在所有 *ngIf
中写一个 *ngIf
=46=]s.
Observable 本质上是惰性的。在您订阅它们之前,它们不会被执行。要查看“点击有效”,您需要订阅它。
this.data$.pipe(tap(data => console.log("tap worked"))).subscribe();
async
默认为您订阅和取消订阅 observable,另外请注意,observable 中的每个订阅者都会获得一个新的执行上下文,并且可以覆盖此行为。
要在订阅晚的情况下缓存结果,您可以在服务中使用 BehaviourSubject
或 ReplaySubject
。
我建议您不要直接订阅 data$
。而是创建另一个您可以阅读的 Observable。
@Input() data$: Observable<any>;
customData$: Observable<any>;
ngOnChanges(changes) {
if(changes.data$) {
console.log("changes detected");
this.customData$ = this.data$.pipe(tap(data => console.log("tap worked")));
}
}
<div *ngIf="customData$ | async as data;">
{{ data || json }}
</div>
我认为问题出在您的 ngOnChanges 中。你有条件
if(changes.data$) {
console.log("changes detected");
this.data$.pipe(tap(data => console.log("tap worked")));
}
这将检查 data$ 的引用是否会更改,但不会检查 data$ 是否发出您真正想要的新值。因此你的点击没有被执行。
相反,你可以
public data$: Observable<any>;
@Input() set data(data$: Observable<any>) {
this.data$ = data$.pipe(tap(x => console.log("tap worked")));
}
免责声明:这与
目前我有两个组件,Parent
和 Child
。
Parent
将一个 Observable 传递给 Child
,它在模板中订阅了这个 Observable 以避免 lifecycle/memory 泄漏问题。但是我必须 pipe
Child
组件中的 Observable 来设置一些东西。
parent.ts:
public $obs = Observable<any>;
....
loadData() {
this.obs$ = this.myService.getData();
}
parent.html:
<child [data$]="obs$"></child>
child.ts:
@Input() data$ : Observable<any>;
ngOnChanges(changes) {
if(changes.data$) {
console.log("changes detected");
this.data$.pipe(tap(data => console.log("tap worked")));
}
}
child.html
<div *ngIf="data$ | async as data;">
{{ data || json }}
</div>
数据存在于模板中,控制台日志显示已检测到更改,但从未显示“tap worked”,这让我怀疑我对 pipe
的调用可能也来了晚的。
有什么方法可以在模板“调用”订阅之前进行管道传输吗?
想法是让许多组件与 child 类似,都对数据做不同的事情 object。我考虑过订阅 Parent
中的服务并将 json 值直接传递给所有 child,但这需要我在所有 *ngIf
中写一个 *ngIf
=46=]s.
Observable 本质上是惰性的。在您订阅它们之前,它们不会被执行。要查看“点击有效”,您需要订阅它。
this.data$.pipe(tap(data => console.log("tap worked"))).subscribe();
async
默认为您订阅和取消订阅 observable,另外请注意,observable 中的每个订阅者都会获得一个新的执行上下文,并且可以覆盖此行为。
要在订阅晚的情况下缓存结果,您可以在服务中使用 BehaviourSubject
或 ReplaySubject
。
我建议您不要直接订阅 data$
。而是创建另一个您可以阅读的 Observable。
@Input() data$: Observable<any>;
customData$: Observable<any>;
ngOnChanges(changes) {
if(changes.data$) {
console.log("changes detected");
this.customData$ = this.data$.pipe(tap(data => console.log("tap worked")));
}
}
<div *ngIf="customData$ | async as data;">
{{ data || json }}
</div>
我认为问题出在您的 ngOnChanges 中。你有条件
if(changes.data$) {
console.log("changes detected");
this.data$.pipe(tap(data => console.log("tap worked")));
}
这将检查 data$ 的引用是否会更改,但不会检查 data$ 是否发出您真正想要的新值。因此你的点击没有被执行。
相反,你可以
public data$: Observable<any>;
@Input() set data(data$: Observable<any>) {
this.data$ = data$.pipe(tap(x => console.log("tap worked")));
}