【问题标题】:Angular component: Can I use an Observable instead EventEmitter as @Output() property?Angular 组件:我可以使用 Observable 而不是 EventEmitter 作为 @Output() 属性吗?
【发布时间】:2017-06-26 10:16:35
【问题描述】:

[角度 2.4.5]

我试过了,它似乎像 EventEmitter 一样工作:

  • 我的外部组件:

    <split (visibleTransitionEnd)="log($event)"></split>
    
  • 组件内部:

    @Output() visibleTransitionEnd: Observable<string>
    observer: Observer;
    
    constructor() {
      const myObs = new Observable(observer => this.observer = observer);
    
      this.visibleTransitionEnd = myObs
        .map(x => '> ' + x + ' <')
        .debounceTime(20)
        .do(() => console.log('here we are!'));
    }
    
  • 然后我可以调用内部组件:

    // needed condition because if nobody subscribe 'visibleTransitionEnd' > no observer!
    if(this.observer) this.observer.next('test');
    

View this plunker

我喜欢这个,因为我的组件中没有订阅。

但这是实现这一目标的坏方法吗?有什么风险/错误?

使用Subject 更好吗?

【问题讨论】:

标签: angular rxjs eventemitter


【解决方案1】:

EventEmitter 只是扩展了Subject,所以这并不奇怪(我也已经在 Dart 中看到了这一点)。

他们使用自己的类以便以后能够在不破坏现有代码的情况下更改实现。

因此,绕过这种抽象可能不是最好的主意。如果你意识到缺点并愿意接受,你当然可以做到。

【讨论】:

  • 你知道是否可以使用 .publishReplay/publish + refCount 并将其标记为@Output?
  • 我不知道,但应该不难发现。
  • 打开了一个功能请求,以将来安全的方式将可观察对象公开为输出属性:github.com/angular/angular/issues/23435
【解决方案2】:

好吧,在您的情况下,您可以使用EventEmitterSubject。您可以看到EventEmitter 就像Subject 一样(尽管如果可以,建议使用EventEmitter)。 https://github.com/angular/angular/blob/master/modules/%40angular/facade/src/async.ts

Observable.create(或new Observable())不适合这样使用。内部函数应该向观察者发出值并返回一个拆卸函数(释放资源或其他)。不得作为财产保留。
但是,我不确定它可能会产生什么后果(内存泄漏?)。

所以宁愿改用Subject

export class SplitComponent implements OnDestroy {
  @Output() visibleTransitionEnd: Observable<string>
  visibleTransitionEndObserver: Subject;

  constructor() {
    const subject = new Subject();

    this.visibleTransitionEnd = subject.asObservable()
      .map(x => '> ' + x + ' <')
      .debounceTime(20)
      .do(() => console.log('here we are!'));
  }

  // ...
}

【讨论】:

【解决方案3】:

选择 EventEmitter 的 2 个理由

  1. Angular EventEmitter 可以确保在需要时异步传递事件。它有利于响应式用户体验。
  2. 封装下划线实现。如果有一天,Angular 的下一个版本将更新依赖于 EventEmitter 的新内容的事件绑定。如果广泛使用Subject,那将是您项目的灾难。不确定这一点。但应该避免。

Angular EventEmitter 扩展了 RxJS Subject,到目前为止只有 3 种方法:1)constructor(),2)subscribe(next, error, complete) 和 3)新方法 emit(value) {super.next(value);}

如果你new EventEmitter(true),它将异步传递事件

    constructor(isAsync = false) {
        super();
        this.__isAsync = isAsync;
    }

EventEmitter.subscribe() 根据this._isAsyncasync 传递事件做一些事情。

【讨论】:

    【解决方案4】:

    我想指出使用 Observable 作为输出接口的一个优势是 你基本上可以抛出任何你想要的 observable

    因此,如果您有一个仅在表单有效时触发并传递值的事件,请说一下。

    使用事件发射器,您必须定义额外的 Emitter 实例来处理该事件

    @Output validValue = new EventEmitter()
    this.form.valueChanges.pipe(tap(value=>{
    if(ths.form.valid) 
       validValue.emit(value)
    })).subscribbe()
    

    使用 Observable 作为事件发射,您可以简单地做到这一点

    @Output() validValue=this.form.valueChanges.pipe(filter(_=>this.form.valid))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      • 1970-01-01
      • 2017-11-16
      • 1970-01-01
      • 1970-01-01
      • 2018-12-25
      相关资源
      最近更新 更多