Angular RxJS 如何在HTML中将Observable对象的单个属性作为Observable传给子组件
问题原因
报错的根本原因是(theObject | async)?.neededValue的写法逻辑错误:async管道的作用是把Observable类型的数据流解包为其发射的普通值,因此你传给子组件neededValue$输入属性的实际是number类型的数值,而非子组件预期的Observable<number>,对普通数值调用subscribe方法自然会抛出错误。再加上你初始化时BehaviorSubject的默认值为null,可选链返回undefined,最终触发Cannot read property 'subscribe' of undefined报错。
另外你的service代码存在笔误:getTheObject方法当前返回的是普通对象this.theObject,需要改为返回this.theObject$才能拿到正确的Observable数据流。
解决方案
以下两种方案都满足「不在父组件内额外创建Observable、不向子组件传递完整大对象」的要求,可按需选择:
方案1:调整子组件输入类型(最简洁)
直接修改子组件的输入属性类型为普通值,依托Angular的输入属性自动更新机制完成响应,完全不需要手动订阅:
- 子组件代码调整:
// Custom Component some: number; @Input() neededValue: number;
- 父组件模板调整:
<app-custom-component [neededValue]="(theObject | async)?.neededValue"></app-custom-component>
调整后neededValue会随父组件的Observable发射新值自动更新,子组件可以直接使用该值。
方案2:封装通用属性提取管道(子组件必须接收Observable时使用)
如果子组件的逻辑必须接收Observable类型的输入,可以封装一个全局通用的管道,一次封装后所有组件都可以在模板中直接提取Observable对象的属性:
- 新建
pluck.pipe.ts:
import { Pipe, PipeTransform } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Pipe({ name: 'pluck', pure: true }) export class PluckPipe implements PipeTransform { transform<T>(obs: Observable<T>, propKey: keyof T): Observable<T[typeof propKey]> { return obs.pipe(map(val => val?.[propKey])); } }
- 将该管道添加到对应模块的
declarations数组中,然后直接在模板中使用:
<app-custom-component [neededValue$]="theObject | pluck:'neededValue'"></app-custom-component>
内容的提问来源于stack exchange,提问作者Sergey Kudryashov
相关产品推荐
相关产品推荐

