0%

Communication between components/directives by service

组件(指令)间通信是Angular中一个非常常见的需求,对于有直接嵌套关系(比如父子组件)的组件,我们可以使用@Input和@Output来实现通信,但是对于没有嵌套关系的组件(亦或者嵌套层级很深的组件),我们就需要使用其他的方法来实现通信了,比如使用服务来实现组件间通信。
下面这个例子就是两个没有嵌套关系的指令之间通信的例子,我们将使用服务来实现这个功能。
注意:在Angular中,组件和指令是一样的,组件是一种特殊的指令。

Create a service

首先我们需要创建一个服务,用于组件间通信。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
providedIn: 'root'
})
export class CommunicationService {
private messageSource = new Subject<string>();

// 此变量的类型是Observable,用来接收消息, message$.subscribe()用来订阅消息。
public message$ = this.messageSource.asObservable();

// 此函数用来发消息
sendMessage(message: string) {
this.messageSource.next(message);
}
}

Directive(Send message)

该指令使用上面定义的service发送消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { Directive, HostListener } from '@angular/core';
import { CommunicationService } from './communication.service';

@Directive({
selector: '[senderDirective]'
})
export class SenderDirective {
constructor(private communicationService: CommunicationService) {}

@HostListener('click')
onClick() {
// 发送消息
this.communicationService.sendMessage('Hello from sender directive!');
}
}

Directive(Receive message)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
该指令使用上面定义的service接收消息
import { Directive } from '@angular/core';
import { CommunicationService } from './communication.service';

@Directive({
selector: '[receiverDirective]'
})
export class ReceiverDirective {
constructor(private communicationService: CommunicationService) {
// 接收消息
this.communicationService.message$.subscribe(message => {
console.log('Received message:', message);
});
}
}

AppModule

我们需要在appModule中声明这两个指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { CommunicationService } from './communication.service';
import { SenderDirective } from './sender.directive';
import { ReceiverDirective } from './receiver.directive';

@NgModule({
declarations: [
AppComponent,
SenderDirective,
ReceiverDirective
],
imports: [
BrowserModule
],
providers: [CommunicationService],
bootstrap: [AppComponent]
})
export class AppModule { }

Usage

1
2
<button senderDirective>Send message</button>
<div receiverDirective></div>