Angular使用Service实现非兄弟组件传值失败,是否需在模块注册Provider?
Angular服务跨组件传值问题修复方案
1. 服务注册说明
必须将DataService添加到对应模块的providers配置中。
Angular通过依赖注入管理服务实例,未在模块providers注册的服务,不同组件注入时会生成独立实例,无法实现数据共享。建议优先在根模块AppModule的providers数组中注册,保证全应用只有一个服务实例。注意不要在单个组件的providers中注册该服务,否则会生成多实例导致数据不通。
2. 现有代码错误点修复
2.1 DataService优化
- 补充
@Injectable()装饰器,满足依赖注入要求 - 替换
Subject为BehaviorSubject,避免「先发值后订阅收不到数据」的时序问题
修正后代码:
import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; @Injectable() export class DataService { private isConfirm = new BehaviorSubject<boolean>(false); sentIsConfirm(isConfirm: boolean) { this.isConfirm.next(isConfirm); } getIsConfirm(): Observable<boolean> { return this.isConfirm.asObservable(); } }
2.2 组件1代码修复
修正参数变量名大小写错误:
constructor(private dataService: DataService) {} isConfirm: boolean = true; leave() { // 原代码变量名写为this.Confirm,和定义的isConfirm大小写不一致 this.dataService.sentIsConfirm(this.isConfirm); }
2.3 组件2代码修复
- 修正
canExit方法返回值类型,适配路由守卫要求,不要在方法内部直接subscribe - 增加订阅销毁逻辑,避免内存泄漏
修正后代码:
import { Subscription } from 'rxjs'; import { tap } from 'rxjs/operators'; confirmation: boolean; private subscription: Subscription; constructor(private dataService: DataService) {} canExit(): Observable<boolean> { return this.dataService.getIsConfirm().pipe( tap(isConfirm => { console.log(isConfirm); this.confirmation = isConfirm; }) ); } ngOnDestroy() { this.subscription?.unsubscribe(); }
3. 问题排查步骤
- 检查服务注册位置,确认只在模块providers中注册了一次
DataService,可以在DataService的constructor中打印日志,运行时如果只打印一次说明是单实例,符合要求 - 触发组件1的
leave方法,在sentIsConfirm中打日志确认方法正常调用,传值正确 - 如果仍收不到值,检查组件2的订阅时机,若使用原始
Subject,必须保证组件2完成订阅后组件1再发值才能收到,BehaviorSubject无需考虑这个问题
内容的提问来源于stack exchange,提问作者Hans
相关产品推荐
相关产品推荐

