Angular组件:我可以使用Observable而不是EventEmitter作为@Output()属性吗?

时间:2017-02-08 16:56:21

标签: angular rxjs eventemitter

[棱角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是否更好?

4 个答案:

答案 0 :(得分:9)

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

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

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

答案 1 :(得分:6)

嗯,在您的情况下,您可以使用EventEmitterSubject。您可以看到EventEmitterSubject一样(尽管如果可以的话,建议使用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!'));
  }

  // ...
}

答案 2 :(得分:0)

选择EventEmitter的2个理由

  1. 角度EventEmitter可以确保在需要时异步传递事件。这对于响应式用户体验很有用。
  2. 封装下划线实现。如果有一天,Angular的下一版本将更新事件绑定,这取决于EventEmitter的新特性。如果Subject被广泛使用,那将对您的项目造成灾难。对此不确定。但是应该避免。

到目前为止,Angular EventEmitter仅使用3种方法扩展了RxJS Subject: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._isAsync进行异步交付事件。

答案 3 :(得分:0)

我想指出的是将Observable用于输出接口的优点是 您基本上可以抛出任何想要的可观察对象

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

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

@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))