Angular中如何将两个服务实例分别传给router-outlet与MatDialog中的组件
解决方案
最优实现方式是利用Angular的分层依赖注入特性,分别给两个Client组件的渲染入口配置独立的服务提供者,无需额外添加ID标识区分发送方,天然实现实例隔离,具体实现步骤如下:
步骤1:调整服务注解,取消全局单例
先去掉ComService的providedIn: 'root'配置,避免默认注册为全局单例:
interface ChildInput { someData: number; } interface ParentInput { someData: string; } // 移除providedIn全局注册配置 @Injectable() export class ComService { pushToChild(data: ParentInput) { // 原有逻辑不变 } pushToParent(data: ChildInput) { // 原有逻辑不变 } // 两个Observable定义不变 }
步骤2:给路由配置独立的服务提供者
在路由定义中给/new-client路由单独添加ComService的提供者,这样路由渲染的Client组件会拿到独有的服务实例:
const routes: Routes = [ // 其他路由配置 { path: 'new-client', component: ClientComponent, // 给当前路由配置独立的服务提供者 providers: [ComService] } ];
步骤3:在App组件中获取两个独立的服务实例
分别监听路由激活事件获取路由侧的服务实例,打开弹窗时直接从Dialog注入器中获取弹窗侧的服务实例:
import { ActivationEnd, Router } from '@angular/router'; import { MatDialog } from '@angular/material/dialog'; import { ComService } from './com.service'; import { ClientComponent } from './client/client.component'; export class AppComponent { // 分别存储两个Client对应的独立服务实例 routerComService?: ComService; dialogComService?: ComService; constructor( private router: Router, private dialog: MatDialog ) { // 监听路由激活事件,获取路由侧Client的服务实例 this.router.events.subscribe(event => { if (event instanceof ActivationEnd) { this.routerComService = event.snapshot.injector.get(ComService, null); // 订阅路由侧Client发送的消息 this.routerComService?.parentObservable?.subscribe(data => { // 此处收到的消息天然来自路由内的Client,无需额外标识区分 console.log('来自路由Client的消息:', data); }); } }); } openClientPopup() { const dialogRef = this.dialog.open(ClientComponent, { // 给弹窗配置独立的服务提供者,生成独立的ComService实例 providers: [ComService] }); // 获取弹窗侧Client的服务实例 this.dialogComService = dialogRef.injector.get(ComService); // 订阅弹窗侧Client发送的消息 this.dialogComService?.parentObservable?.subscribe(data => { // 此处收到的消息天然来自弹窗内的Client console.log('来自弹窗Client的消息:', data); }); } // 主动给对应Client发数据的示例 sendToRouterClient(data: ParentInput) { this.routerComService?.pushToChild(data); } sendToDialogClient(data: ParentInput) { this.dialogComService?.pushToChild(data); } }
方案说明
该方案完全符合Angular框架的依赖注入设计规范:
- 路由和MatDialog都支持自定义注入器配置,分别配置
ComService提供者后会自动生成两个完全独立的服务实例,分别绑定到对应的Client组件 - 两个实例的Observable互相隔离,订阅不同实例的流即可直接区分消息来源,无需额外加ID做判断
- 组件销毁时对应的服务实例会被注入器自动回收,不会产生内存泄漏
内容的提问来源于stack exchange,提问作者kos
相关产品推荐
相关产品推荐

