【问题标题】:Angular Components - Output encapsulating a BehaviorSubjectAngular 组件 - 封装 BehaviorSubject 的输出
【发布时间】:2020-02-10 15:02:35
【问题描述】:

我有一个具有内部状态的组件,存储在 RxJS 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&lt;T&gt; 一样。

【问题讨论】:

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

标签: angular rxjs


【解决方案1】:

Angular 中的EventEmitter 是 RxJS Subject 的简单扩展。所以理论上我们应该能够通过扩展BehaviorSubject而不是Subject来创建自定义发射器来实现您的预​​期行为。一个粗略的实现是:

import { BehaviorSubject } from 'rxjs/BehaviorSubject';

export class BehaviorEventEmitter<T extends any> extends BehaviorSubject<T> {

  constructor(initial: any) {
    super(<any>(initial));
  }

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

}

我可以看到的一个缺点是,如果尚未发出其他值,它会在相关组件加载到 DOM 时立即发出 initial 参数的值。

工作示例:Stackblitz

【讨论】:

    【解决方案2】:

    您需要更新您的子组件中的 behaviorSubject 值,如下所示

    this._state$.next(somevalue);

    那么behaviourSubject订阅将发出statechange输出装饰器。

    参考:https://stackblitz.com/edit/angular-vfjzwh?file=src%2Fapp%2Fapp.component.html

    【讨论】:

    • 我不明白这是如何回答这个问题的。是的,我知道如何从主题中发出值。问题是:“如果 PARENT 组件尚未订阅怎么办?”
    • 如果可能的话,你能在 stackblitz.com 上做吗
    猜你喜欢
    • 1970-01-01
    • 2016-02-26
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 2016-04-14
    • 2020-10-31
    相关资源
    最近更新 更多