Angular组件 - 封装BehaviorSubject的输出

7

我有一个组件,它包含一个保存在RxJS BehaviorSubject (顺便说一下,这个BehaviorSubject 保存了某个DOM元素的大小)中的内部状态。

我想把这个状态作为一个@Output()属性暴露出来。

我能想到最朴素的实现方式如下:

// inside myComponent

private _state$ = new BehaviorSubject<Something>(...);

@Output() stateChange = new EventEmitter<Something>();

constructor() {
  // skipping unsubscription for the sake of this simplistic example
  this._state$.subscribe(newState => this.stateChange.emit(newState);
}


然而,这不会像BehaviorSubject一样在有新订阅时立即发出当前存储的值。晚订阅者将不会获取到当前值。
对于这种情况,是否有简单的方法?我想公开状态并基本上不再担心事件的顺序,就像使用简单的BehaviorSubject<T>一样。

暴露 this._state$.asObservable() 有问题吗?编辑:我猜问题是你想像 (stateChange)="onStateChange($event)" 这样绑定它? - Kurt Hamilton
@KurtHamilton 是的,我想使用(stateChange)语法。而且,我不想关心父组件何时订阅。 - Alberto Chiesa
这是一个相当有趣的问题。在没有干净的解决方法的情况下(肮脏的方法是分叉EventEmitter并从BehaviorSubject继承),我得出结论,混合javascript事件处理和rxjs的隐喻可能不是一个好的做法(尽管Angular现在很高兴这样做...)。但我很想看看你最终会做什么,所以如果你找到了一个好的解决方案,请通过此评论链提醒我。 - Kurt Hamilton
2个回答

1
在Angular中,EventEmitter是RxJS Subject的简单扩展。因此,理论上我们应该能够通过扩展BehaviorSubject而不是Subject来创建自定义发射器,以实现您期望的行为。一个简单的实现方式如下:
import { BehaviorSubject } from 'rxjs';
    
export class BehaviorEventEmitter<T extends any> extends BehaviorSubject<T> {
  constructor(initial: any) {
    super(<any>(initial));
  }

  emit(value?: T) { super.next(value); }
}

我能看到的一个缺点是,如果在相关组件加载到DOM中时还没有发出其他值,它将立即发出initial参数的值。
工作示例:Stackblitz

-1

我不认为这回答了问题。是的,我知道如何从Subject中发出一个值。问题是:“如果父组件尚未订阅怎么办?” - Alberto Chiesa
如果可能的话,你能在stackblitz.com上完成吗? - Arunkumar Ramasamy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接