免责声明:这与此问题密切相关。
目前我有两个组件,Parent
和Child
。Parent
将一个Observable传递给Child
,后者在模板中订阅该Observable以避免生命周期/内存泄漏问题。但我必须在Child
组件中pipe
的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的组件,所有组件都在数据对象上做不同的事情。我考虑订阅Parent
中的服务,并将json值直接传递给所有子级,但这需要我在所有子级中编写一个*ngIf
。
我建议您不要直接订阅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>
观察者天生懒惰。在您订阅它们之前,它们不会被执行。要查看";tap-worked";你需要订阅它。
this.data$.pipe(tap(data => console.log("tap worked"))).subscribe();
默认情况下,async
为您订阅和取消订阅observable,还请注意,observable中的每个订阅程序都会获得一个新的执行上下文,并且这种行为可以被覆盖。
为了在订阅延迟的情况下缓存结果,您可以在服务中使用BehaviourSubject
或ReplaySubject
。
我认为问题出在ngOnChanges中。你有条件
if(changes.data$) {
console.log("changes detected");
this.data$.pipe(tap(data => console.log("tap worked")));
}
这将检查数据$的引用是否会更改,但不检查数据$是否发出您实际想要的新值。因此,您的tap不会执行。
相反,你可以
public data$: Observable<any>;
@Input() set data(data$: Observable<any>) {
this.data$ = data$.pipe(tap(x => console.log("tap worked")));
}