我读过像Access EventEmitter Service inside of CustomHttp这样的问题,用户在他的服务中使用了EventEmitter,但是他在这个comment中建议不要使用它,而是直接在他的服务中使用Observables。
我还读了这个question,解决方案建议将EventEmitter传递给孩子并订阅它。
我的问题是:我应该,还是不应该手动订阅EventEmitter?我该怎么用?
EventEmitter是一个angular2抽象,它的唯一目的是在组件中发出事件。引自Rob Wormald的comment
[...] EventEmitter实际上是一个Angular抽象,应该只用于在组件中发出自定义事件。否则,只需使用Rx就好像它是任何其他库一样。
在EventEmitter的文档中说明了这一点。
指令和组件使用它来发出自定义事件。
Angular2永远不会保证我们EventEmitter将继续作为Observable。所以这意味着如果代码发生变化就重构代码。我们必须访问的唯一API是它的emit()
方法。我们永远不应该手动订阅EventEmitter。
上面提到的所有内容在这个Ward Bell的comment中更清楚(建议阅读文章,answer到那个评论)。引用以供参考
不要指望EventEmitter继续是一个Observable!
不要指望将来存在的Observable运营商!
这些将很快被弃用,并可能在发布之前删除。
仅将EventEmitter用于子组件和父组件之间的事件绑定。不要订阅它。不要调用任何这些方法。只能打电话给
eve.emit()
他的评论很久以前就与Rob的评论一致。
只需使用它从组件中发出事件即可。看一下下面的例子。
@Component({
selector : 'child',
template : `
<button (click)="sendNotification()">Notify my parent!</button>
`
})
class Child {
@Output() notifyParent: EventEmitter<any> = new EventEmitter();
sendNotification() {
this.notifyParent.emit('Some value to send to the parent');
}
}
@Component({
selector : 'parent',
template : `
<child (notifyParent)="getNotification($event)"></child>
`
})
class Parent {
getNotification(evt) {
// Do something with the notification (evt) sent by the child!
}
}
class MyService {
@Output() myServiceEvent : EventEmitter<any> = new EventEmitter();
}
停在那儿......你已经错了......
希望这两个简单的例子能够澄清EventEmitter的正确用法。
TL; DR回答:
不,不要手动订阅它们,不要在服务中使用它们。仅按文档中的说明使用它们以在组件中发出事件。不要打败角度的抽象。
EventEmitter
是最终Angular Core API中的public, documented type。它是否基于Observable
是无关紧要的;如果它记录的emit
和subscribe
方法适合您的需要,那么继续使用它。
正如文档中所述:
使用Rx.Observable但提供适配器使其按照此处的指定工作:https://github.com/jhusain/observable-spec
一旦规范的参考实现可用,切换到它。
所以他们想要一个像某种方式表现出来的Observable
对象,他们实现了它并将其公之于众。如果它只是一个不应该使用的内部Angular抽象,它们就不会公开。
有很多时候,有一个发送器发送特定类型的事件是有用的。如果这是你的用例,那就去吧。如果/当他们链接到的规范的参考实现可用时,它应该是替代品,就像任何其他polyfill一样。
请确保传递给subscribe()
函数的生成器遵循链接规范。返回的对象保证有一个unsubscribe
方法,应该调用它来释放对生成器的任何引用(这是一个RxJs Subscription
object,但这确实是一个不应该依赖的实现细节)。
export class MyServiceEvent {
message: string;
eventId: number;
}
export class MyService {
public onChange: EventEmitter<MyServiceEvent> = new EventEmitter<MyServiceEvent>();
public doSomething(message: string) {
// do something, then...
this.onChange.emit({message: message, eventId: 42});
}
}
export class MyConsumer {
private _serviceSubscription;
constructor(private service: MyService) {
this._serviceSubscription = this.service.onChange.subscribe({
next: (event: MyServiceEvent) => {
console.log(`Received message #${event.eventId}: ${event.message}`);
}
})
}
public consume() {
// do some stuff, then later...
this.cleanup();
}
private cleanup() {
this._serviceSubscription.unsubscribe();
}
}
所有强硬措辞的厄运和悲观预测似乎源于单个开发人员在Angular 2预发布版本上发出的单一Stack Overflow评论。
当您想要进行跨组件交互时,您需要知道@Input,@ Output,EventEmitter和Subjects是什么。
如果组件之间的关系是父子关系,反之亦然,我们使用@input&@ output与事件发射器。
@output发出一个事件,你需要使用事件发射器发出。
如果它不是父母子女关系..那么你必须使用科目或通过共同的服务。
从一个非常合乎逻辑的角度来看。如果您有一个组件并且您想要通知其他组件发生了某些事情,则应该触发一个事件。我没有看到不使用它的原因。此外,EventEmitter名称也向我建议发生了一件事。我通常将它用于组件范围内发生的重要事件。我创建服务但在组件文件夹中创建服务文件。所以我的服务文件变成了一种事件管理器或事件接口,所以我可以一眼就知道我可以在当前组件上订阅哪个事件。
我知道......也许我是一个老有魅力的开发者。
但这被称为:事件驱动的开发模式。
其他一些人可能认为Observables很酷。在那种情况下继续使用Observables。到目前为止,你不是凶手这样做的程序工作。
没有:nono和no:yesyes。