使用单个服务在不相关的组件之间进行通信

时间:2019-06-01 16:27:40

标签: angular

我正在使用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,这将使所有与其他组件通信的组件都订阅他们不希望接收和不需要接收的信息。 应该使用哪种方法?

1 个答案:

答案 0 :(得分:1)

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

{ 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> {
}