【问题标题】:Using a single service to communicate between unrelated components使用单个服务在不相关的组件之间进行通信
【发布时间】:2019-06-02 01:14:15
【问题描述】:

我正在开发一个 Angular 7 应用程序。我的项目中发生了很多跨组件通信,并且组件没有父子关系。

据我所知,此类问题的一个很好的解决方案是服务。我可以有一个服务来处理应用程序范围内的所有通信(信息会非常不同),还是我必须为每对组件编写不同的服务?这似乎是很多重复的代码。否则,如果在需要发送或接收信息的每个组件中使用,在每次订阅时,它实际上都会订阅通过该服务发送的所有信息,这绝对不是所需的行为。

我的服务如下所示:

@Injectable({providedIn: 'root'})
export class ComponentService {
  private subject = new Subject<any>();

  sendData(data: any) {
    this.subject.next(data);
  }

  getData(): any {
    return this.subject.asObservable();
  }
}

信息是这样发送的:

this.componentService.sendData(element);

并且像这样在另一个组件中接收:

 constructor(private componentService: ComponentService) {
  }

  ngOnInit() {
    this.componentService.getData().subscribe(data => data);
  }

显然,如果 ComponentService 在整个应用程序中使用,这将使所有组件(与其他组件通信)订阅他们不希望接收的信息,也不需要接收。 应该使用什么方法?

【问题讨论】:

  • 您是否考虑过调查ngrx?如果您要在整个应用程序中管理大量状态,那么它可能是一个不错的选择。
  • 我对 React 不是很熟悉,据我所知,ngrx 就是从那里获得灵感的。不过我可能会看看。

标签: angular


【解决方案1】:

从技术上讲,您可以拥有一个带有 Subject 的服务,该服务发出一个对象,该对象具有确定数据类型的属性,例如:

{ type: 'CustomerId', value: 35 }

但是,您不会从 TypeScript 的类型提示中受益。 TypeScript 的好处是你可以声明一个类型别名/接口(如CustomerData),然后有一个类型化的主题来发出这些数据:

private subject: Subject<CustomerData> = new Subject<CustomerData>();

当您在组件中订阅此主题时,您将获得一个类型化的结果,而不是 any 类型,应尽可能谨慎使用(或从不使用)。

如果您担心代码重复,您可以创建一个抽象的通用基础服务并让您的其他服务扩展它:

@Injectable({providedIn: 'root'})
export abstract class BaseComponentService<T> {
  private subject = new Subject<T>();

  sendData(data: T) {
    this.subject.next(data);
  }

  getData(): any {
    return this.subject.asObservable();
  }
}

因此,当您创建新服务时,您可以使用定义的类型扩展类:

type SubType = {
  name: string;
  age: number;
};

@Injectable()
export class SubService extends BaseComponentService<SubType> {
}

【讨论】:

  • 感谢您的回答!尽管如此,类型在我的情况下并不会真正有帮助。我发送的主要是字符串或数字;这还不足以识别
  • 如果你有多个组件监听同一个服务并发出不同的数字/字符串,你怎么知道它是什么类型的数据?如果您不使用类型别名/接口,那很好,但您至少应该发出一个描述数据类型的对象{type: 'customerId', value: 35}。否则,您的组件将如何知道发出的值代表什么?也许一个组件会期待来自 Subject 的数字 id,而另一个会等待一定数量的钱。如果主题发出 35,您将不知道这是代表 id 还是金额
  • 到目前为止,这正是我的方法,形成了您提到的类型的对象。但不知何故,每次订阅时都收到发送的所有内容似乎是错误的,我觉得我的做法不对。
  • 为了发出一个主题值的单一目的而创建许多服务似乎很浪费,但通常服务包含与服务目的相关的其他功能。就像 CustomerService 可能会为某些组件发出一个客户 ID,以便它可以更新它的视图,但该服务也可以用于检索、创建、更新和删除客户,并具有与此相关的功能
  • 是的,你是对的!我将使用您提到的扩展服务的方法。这看起来是我现在最好的方法。感谢您的时间和解释!
猜你喜欢
  • 1970-01-01
  • 2018-08-07
  • 2018-09-10
  • 2010-09-29
  • 2019-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多