【问题标题】:Create EvenEmitter dynamically in Angular在 Angular 中动态创建 EvenEmitter
【发布时间】:2017-08-22 21:20:29
【问题描述】:

我正在尝试在 Angular 中使用 EventEmitter 来实现观察者类型的模式。

例如,我有一个名为 component1Publisher 的发布者

component1Publisher: EventEmitter<any> = new EventEmitter();

发布如下事件

this.component1Publisher.emit(data);

订阅多个组件,如下所示

component1Publisher.subscribe((data:any) => {
            //do something here;

          });

您可以看到发布者是静态声明的。在我的项目中发布者和订阅者是完全动态的。所以我想根据我唯一的组件名称创建这个 EventEmitter 实例和订阅者。如下所示

createEvent(uniqueName:string){
//new unique eventEmitter
}

我的问题 我有一个可重用的框架来创建一个仪表板,用户可以带来框架本身提供的小部件。所以我试图在小部件之间进行通信以使其具有交互性。例如,当您单击小部件时,应通知所有其他小部件。为此,我打算告诉用户提供动态服务。在动态服务中有一些方法,如 onWidgetClick(),它会通过动态解析服务来由框架触发。在该方法中,用户可以创建要发布的事件。它将用新数据通知所有小部件,框架将用新数据更新它(所有可重用的小部件都有订阅者)。

你能帮我解决这个问题吗,或者建议有没有其他方法可以实现这种实现

【问题讨论】:

  • 根据实际需求更新问题

标签: angular observer-pattern eventemitter


【解决方案1】:

我会在“this”所指的任何组件/指令中定义一个映射(我认为这是正确的术语?)。比如:

componentPublishers: { [index:string] : EventEmitter<any> } = {};

该代码只是说,我正在创建一个包含 EventEmitters 的对象,所有事件均由字符串标识(您可以使用字符串或数字作为标识符,但几乎在所有情况下人们都使用字符串)。

然后,您可以使用括号表示法(在 JS 中用于向对象添加新属性)以您喜欢的任何名称添加 EventEmitters。

createEvent(uniqueName:string){
  this.componentPublishers[uniqueName] = new EventEmitter<any>();

 // and maybe you'd want to return it?

  return this.componentPublishers[uniqueName];
}

创建后,您应该能够像平常一样访问它而无需括号符号。通过使用上面显示的地图,typescript 将知道 componentPublishers 对象的任何属性都是事件发射器。

this.componentPublishers.myNewEventEmitter.emit('some value');

注意:如果你尝试使用括号表示法向对象添加属性,如果你没有先实例化它,你会得到错误。我只是将它实例化为一个空对象。

 ... =  {};

所以一定要这样做。

您也可以只创建一个事件发射器数组并将新的发射器推入其中,但这很快就会变得笨拙,因为您必须跟踪索引。通过使用映射,您可以像常规对象一样按名称访问它们,并且仍然具有 Typescript 的静态类型检查。

【讨论】:

  • 我觉得不错。让我试试这个解决方案。我已经根据实际要求更新了我的问题。你认为@DeborahK 提供的解决方案能满足我的需要吗?我认为没有 observable 是不可能的
  • 我认为你是正确的 observables 将是最好的解决方案。您也可以尝试创建 rxjs 主题而不是 EventEmitters。它们可能更容易处理,并且为您提供更多选择。另一件事可能会有所帮助...您可以通过从“rxjs/Subscription”导入“Subscription”来强制处理订阅。如果您不断发送 Observables,然后在大多数情况下收件人会立即订阅它们,这可以为您节省一些重复编码。如果小部件/组件/任何东西被破坏,它还可以让您取消订阅。
  • 我同意我在某处看到使用 rxJS 主题。感谢您的解决方案。我也会试试的。
【解决方案2】:

根据您最终要完成的任务,可能不需要这样做。您可以利用 Angular 的变更检测来提供您需要的通知。

例如,您可以这样设置服务:

import { Injectable } from '@angular/core';

@Injectable() 
export class DataService {
  serviceData: string; 
}

任何绑定到该数据的模板都会自动收到更改通知(无需事件)。

我在这里有一篇关于它的博文:https://blogs.msmvps.com/deborahk/build-a-simple-angular-service-to-share-data/

这里有一个笨蛋:https://plnkr.co/edit/KT4JLmpcwGBM2xdZQeI9?p=preview

【讨论】:

  • 它是一个框架,因此用户应该可以选择根据组件名称创建事件。框架已使用唯一名称订阅。因此,每当发布一个事件时,它都会触发所有订阅的组件。在我看来,事件发射器最适合这个要求。
  • 我已经根据我的实际需求更新了我的问题
猜你喜欢
  • 2017-09-10
  • 2017-11-03
  • 2017-07-07
  • 2016-09-27
  • 1970-01-01
  • 2018-09-02
  • 2018-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多