我已经读过诸如CustomHttp内的Access EventEmitter Service之类的问题 ,其中用户在其服务中使用EventEmitter,但在此注释中建议他 不要使用它,而应在其服务中直接使用Observables。
我还读了这个 问题 ,解决方案建议将EventEmitter传递给孩子并订阅它。
然后我的问题是:我应该还是不应该手动订阅EventEmitter?我应该如何使用它?
我已经读过诸如CustomHttp内的Access EventEmitter Service之类的问题 ,其中用户在其服务中使用EventEmitter,但在此注释中建议他 不要使用它,而应在其服务中直接使用Observables。
我还读了这个 问题 ,解决方案建议将EventEmitter传递给孩子并订阅它。
然后我的问题是:我应该还是不应该手动订阅EventEmitter?我应该如何使用它?
Answers:
TL; DR:
不,请勿手动订阅它们,也不要在服务中使用它们。如文档所示,仅使用它们在组件中发出事件。不要打败angular的抽象。
回答:
EventEmitter是angular2抽象,其唯一目的是在组件中发出事件。引用Rob Wormald 的评论
[...] EventEmitter实际上是一个Angular抽象,应仅用于在组件中发出自定义事件。否则,就像其他任何库一样使用Rx。
在EventEmitter的文档中确实很清楚地说明了这一点。
由指令和组件使用以发出自定义事件。
Angular2永远不会保证我们EventEmitter将继续是可观察的。因此,这意味着在代码更改时对其进行重构。我们必须访问的唯一API是emit()
方法。我们绝不应该手动订阅EventEmitter。
在沃德·贝尔(Ward Bell)的评论中(建议阅读本文以及对该评论的回答),上述所有内容都更加清楚。报价以供参考
不要指望EventEmitter继续是可观察的!
不要指望将来会出现那些可观察的运算符!
这些将很快被弃用,并且可能在发布之前将其删除。
仅将EventEmitter用于子组件和父组件之间的事件绑定。不订阅。不要调用任何这些方法。只通话
eve.emit()
他的评论与很久以前罗布的评论一致。
只需使用它即可从您的组件中发出事件。看下面的例子。
@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的正确用法。
directives : [Child]
在组件定义中?这似乎无法编译,我无法在Angular2文档中找到它。
EventEmitter
是最终Angular Core API中公开的,已记录的类型。它是否基于Observable
无关紧要;如果其文档emit
和subscribe
方法适合您的需求,请继续使用它。
正如文档中所述:
使用Rx.Observable,但提供了一个适配器以使其按此处指定的方式工作:https : //github.com/jhusain/observable-spec
一旦该规范的参考实现可用,请切换到该规范。
因此,他们想要一个Observable
行为类似的对象,将其实现并公开。如果只是不应该使用的内部Angular抽象,那么他们就不会将其公开。
很多时候,使用一个发送器来发送特定类型的事件很有用。如果那是您的用例,那就去吧。如果/当它们链接到的规格的参考实现可用时,就应该像其他任何polyfill一样直接替换。
只要确保传递给subscribe()
函数的生成器遵循链接的规范即可。保证返回的对象具有一个unsubscribe
应调用的方法,以释放对生成器的任何引用(当前是RxJs Subscription
对象,但这实际上是不应依赖的实现细节)。
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评论。
没有:nono,没有:是的。真相在中间,没有理由因为下一个版本的Angular而被吓到。
从逻辑的角度来看,如果您有一个组件并且想要通知其他组件某些事情发生了,那么应该触发一个事件,并且可以用您(开发人员)认为应该完成的任何方式来完成。我不明白为什么不使用它的原因,也不知道不惜一切代价使用它的原因。同样EventEmitter的名称也向我暗示了正在发生的事件。我通常将其用于组件中发生的重要事件。我创建了服务,但是在组件文件夹中创建了服务文件。因此,我的服务文件变成了一种事件管理器或事件接口,因此我一眼就能确定可以在当前组件上订阅哪个事件。
我知道。也许我是一个老式的开发人员。但这不是事件驱动开发模式的一部分,这是您特定项目的软件体系结构决策的一部分。
其他一些人可能认为直接使用Observables很酷。在这种情况下,请直接使用Observables。您不是这样做的连环杀手。除非您是一个精神病患者开发人员,否则到目前为止,该程序仍然有效。