正如@bryan60 所提到的,这更多是架构问题,而不是特定于应用程序特定状态的问题。
在我看来,您需要想出一个通用的方法来使用事件在多个组件之间共享数据。
这将导致一个灵活的实现,然后可以在您的应用程序的其他任何地方使用。
我在我的 Angular 应用程序中使用了这样一个基于 observables 的事件服务,它允许组件触发事件,而其他组件可以监听这些事件 -
活动服务
import { Injectable } from "@angular/core";
import * as Rx from 'rxjs/Rx';
import { Observable, Subject } from "rxjs/Rx";
import { UUID } from "./uuid-generator";
export const GLOBAL_EVENTS = {
Test_Event: "Test_Event";
}
/**
*
*
* @class EventListener
*/
class EventListener {
constructor(uuid: string, func: Function) {
if (!uuid || !func) {
console.error("required arguments not provided!");
return;
}
this._uuid = uuid;
this.func = func;
}
private _uuid: string;
public get uuid(): string {
return this._uuid;
}
public func: Function;
}
@Injectable()
export class EventsService {
private eventsSubject: Subject<any>;
private listeners: Map<string, Array<EventListener>>;
public constructor() {
//initialise listeners
this.listeners = new Map();
//initialise event subject
this.eventsSubject = new Rx.Subject();
//listen to the changes in subject
Rx.Observable.from(this.eventsSubject)
.subscribe(({ name, args }) => {
if (this.listeners[name]) {
this.listeners[name].forEach((listener: EventListener) => {
listener.func(...args);
});
}
});
}
/**
* Listens to the event and provides a unique key for the listener
* @method on
* @param {string} name name of the event to be listened to.
* @param {Function} listener listener function with one array argument
* @return {string} returns the key (UUID) for listener function which can be used to stop listening to the event.
* @memberof EventsService
*/
public on(name: string, listener: Function): string {
this.listeners[name] = this.listeners[name] || [];
let listenerEvent: EventListener = new EventListener(UUID.generate(), listener);
this.listeners[name].push(listenerEvent);
return listenerEvent.uuid;
}
/**
* Stops listening to the event by using the unique key for the listener
* @method off
* @param {string} name name of the event to be broadcasted
* @param {string} uuid name of the event listener specific uuid to be removed
* @param {boolean} [removeAll=false] removes all event listeners attached to specified event name
* @returns {void}
* @memberof EventsService
*/
public off(name: string, uuid?: string, removeAll: boolean = false): void {
if (!this.listeners[name] || !this.listeners[name].length) {
return;
}
if (removeAll) {
this.listeners[name] = [];
return;
}
this.listeners[name] = this.listeners[name].filter((item: EventListener, index: number) => {
return item.uuid !== uuid;
});
}
/**
* Broadcasts the event and passes data provided in args argument as event data
* @method broadcast
* @param {string} name name of the event to be broadcasted.
* @param {any} args arguments to be sent with the event.
* @return {void} return void
* @memberof EventsService
*/
public broadcast(name: string, ...args): void {
this.eventsSubject.next({ name, args });
}
}
UUID 生成器
export class UUID {
public static generate(): string {
return "your_hash";
}
}
注册活动
import { Component, OnDestroy } from "@angular/core";
import { EventsService, GLOBAL_EVENTS } from "./events.service";
@Component({
selector: "[app-listener-component]",
templateUrl: "./app-listener-component.html",
styleUrls: ["./app-listener-component.scss"]
})
export class ListenerComponent {
private eventId: string;
public constructor(private _EventsService: EventsService) {
this.eventId = this._EventsService.on(GLOBAL_EVENTS.Test_Event, (response: any) => {
console.log(response);
});
}
public ngOnDestroy(): void {
this._EventsService.off(this.eventId);
}
}
广播消息
import { EventsService, GLOBAL_EVENTS } from "./events.service";
export class BroadcatComponent
public constructor(private _EventsService: EventsService) {
let data: any = {
message: "any"
}
this._EventsService.broadcast(GLOBAL_EVENTS.Test_Event, data);
}
}
要记住的事情
确保在主应用模块中添加服务,以便它在整个应用程序中开始表现为单例服务。
每个事件订阅都会返回一个 UUID 字符串,该字符串可用于删除全局范围内的事件处理程序 (additional features are in code comments)。
使用ngDestroy 删除事件处理程序将确保未使用的事件不会保留在内存中
At last but not the least, I have modified the original code so you might get compilation errors in the sample code.
我希望这会有所帮助:)