Angular中没有等价的$scope.emit()或$scope.broadcast()吗?
我知道EventEmitter功能,但据我所知,它只会向父HTML元素发出一个事件。
如果我需要在fx和。还是DOM根组件和嵌套了几层的元素之间?
Angular中没有等价的$scope.emit()或$scope.broadcast()吗?
我知道EventEmitter功能,但据我所知,它只会向父HTML元素发出一个事件。
如果我需要在fx和。还是DOM根组件和嵌套了几层的元素之间?
当前回答
这是我的版本:
export interface IEventListenr extends OnDestroy{
ngOnDestroy(): void
}
@Injectable()
export class EventManagerService {
private listeners = {};
private subject = new EventEmitter();
private eventObserver = this.subject.asObservable();
constructor() {
this.eventObserver.subscribe(({name,args})=>{
if(this.listeners[name])
{
for(let listener of this.listeners[name])
{
listener.callback(args);
}
}
})
}
public registerEvent(eventName:string,eventListener:IEventListenr,callback:any)
{
if(!this.listeners[eventName])
this.listeners[eventName] = [];
let eventExist = false;
for(let listener of this.listeners[eventName])
{
if(listener.eventListener.constructor.name==eventListener.constructor.name)
{
eventExist = true;
break;
}
}
if(!eventExist)
{
this.listeners[eventName].push({eventListener,callback});
}
}
public unregisterEvent(eventName:string,eventListener:IEventListenr)
{
if(this.listeners[eventName])
{
for(let i = 0; i<this.listeners[eventName].length;i++)
{
if(this.listeners[eventName][i].eventListener.constructor.name==eventListener.constructor.name)
{
this.listeners[eventName].splice(i, 1);
break;
}
}
}
}
emit(name:string,...args:any[])
{
this.subject.next({name,args});
}
}
use:
export class <YOURCOMPONENT> implements IEventListener{
constructor(private eventManager: EventManagerService) {
this.eventManager.registerEvent('EVENT_NAME',this,(args:any)=>{
....
})
}
ngOnDestroy(): void {
this.eventManager.unregisterEvent('closeModal',this)
}
}
发出:
this.eventManager.emit("EVENT_NAME");
其他回答
不要使用EventEmitter来进行服务通信。
你应该使用Observable类型之一。我个人喜欢BehaviorSubject。
简单的例子:
你可以传递初始状态,这里我传递null
let subject = new BehaviorSubject(null);
当你想要更新主题时
next (myObject)科目。
观察任何服务或组件,并在其获得新的更新时采取行动。
subject.subscribe (this.YOURMETHOD);
这里有更多信息。
我在这里创建了一个pub-sub示例:
http://www.syntaxsuccess.com/viewarticle/pub-sub-in-angular-2.0
这个想法是使用RxJs subject来连接一个观察者和和可观察对象,作为一个通用的解决方案来发送和订阅自定义事件。在我的示例中,出于演示目的,我使用了一个customer对象
this.pubSubService.Stream.emit(customer);
this.pubSubService.Stream.subscribe(customer => this.processCustomer(customer));
这里还有一个现场演示: http://www.syntaxsuccess.com/angular-2-samples/#/demo/pub-sub
这是我的版本:
export interface IEventListenr extends OnDestroy{
ngOnDestroy(): void
}
@Injectable()
export class EventManagerService {
private listeners = {};
private subject = new EventEmitter();
private eventObserver = this.subject.asObservable();
constructor() {
this.eventObserver.subscribe(({name,args})=>{
if(this.listeners[name])
{
for(let listener of this.listeners[name])
{
listener.callback(args);
}
}
})
}
public registerEvent(eventName:string,eventListener:IEventListenr,callback:any)
{
if(!this.listeners[eventName])
this.listeners[eventName] = [];
let eventExist = false;
for(let listener of this.listeners[eventName])
{
if(listener.eventListener.constructor.name==eventListener.constructor.name)
{
eventExist = true;
break;
}
}
if(!eventExist)
{
this.listeners[eventName].push({eventListener,callback});
}
}
public unregisterEvent(eventName:string,eventListener:IEventListenr)
{
if(this.listeners[eventName])
{
for(let i = 0; i<this.listeners[eventName].length;i++)
{
if(this.listeners[eventName][i].eventListener.constructor.name==eventListener.constructor.name)
{
this.listeners[eventName].splice(i, 1);
break;
}
}
}
}
emit(name:string,...args:any[])
{
this.subject.next({name,args});
}
}
use:
export class <YOURCOMPONENT> implements IEventListener{
constructor(private eventManager: EventManagerService) {
this.eventManager.registerEvent('EVENT_NAME',this,(args:any)=>{
....
})
}
ngOnDestroy(): void {
this.eventManager.unregisterEvent('closeModal',this)
}
}
发出:
this.eventManager.emit("EVENT_NAME");
服务事件:组件可以订阅服务事件。例如,两个兄弟组件可以订阅相同的服务事件,并通过修改各自的模型进行响应。下文将详细介绍。
但是要确保在销毁父组件时取消订阅。
我正在使用一个消息服务,包装rxjs主题(TypeScript)
Plunker示例:Message Service
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/filter'
import 'rxjs/add/operator/map'
interface Message {
type: string;
payload: any;
}
type MessageCallback = (payload: any) => void;
@Injectable()
export class MessageService {
private handler = new Subject<Message>();
broadcast(type: string, payload: any) {
this.handler.next({ type, payload });
}
subscribe(type: string, callback: MessageCallback): Subscription {
return this.handler
.filter(message => message.type === type)
.map(message => message.payload)
.subscribe(callback);
}
}
组件可以订阅和广播事件(发送方):
import { Component, OnDestroy } from '@angular/core'
import { MessageService } from './message.service'
import { Subscription } from 'rxjs/Subscription'
@Component({
selector: 'sender',
template: ...
})
export class SenderComponent implements OnDestroy {
private subscription: Subscription;
private messages = [];
private messageNum = 0;
private name = 'sender'
constructor(private messageService: MessageService) {
this.subscription = messageService.subscribe(this.name, (payload) => {
this.messages.push(payload);
});
}
send() {
let payload = {
text: `Message ${++this.messageNum}`,
respondEvent: this.name
}
this.messageService.broadcast('receiver', payload);
}
clear() {
this.messages = [];
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
(接收方)
import { Component, OnDestroy } from '@angular/core'
import { MessageService } from './message.service'
import { Subscription } from 'rxjs/Subscription'
@Component({
selector: 'receiver',
template: ...
})
export class ReceiverComponent implements OnDestroy {
private subscription: Subscription;
private messages = [];
constructor(private messageService: MessageService) {
this.subscription = messageService.subscribe('receiver', (payload) => {
this.messages.push(payload);
});
}
send(message: {text: string, respondEvent: string}) {
this.messageService.broadcast(message.respondEvent, message.text);
}
clear() {
this.messages = [];
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
MessageService的subscribe方法返回一个rxjs订阅对象,可以像这样取消订阅:
import { Subscription } from 'rxjs/Subscription';
...
export class SomeListener {
subscription: Subscription;
constructor(private messageService: MessageService) {
this.subscription = messageService.subscribe('someMessage', (payload) => {
console.log(payload);
this.subscription.unsubscribe();
});
}
}
也可以看到这个答案:https://stackoverflow.com/a/36782616/1861779
Plunker示例:Message Service