Angular组件未初始化时事件发射器数据传递失效的解决方法
问题解决方法
你的核心问题是事件发射时机早于组件订阅时机,导致env-risk组件初始化时没接收到floating-button发射的日期数据。可以通过以下两种方案解决:
方案一:用BehaviorSubject替代EventEmitter(推荐)
普通的EventEmitter/Subject不会保存历史值,只有订阅之后发射的事件才能被接收。而BehaviorSubject会缓存最新的一次值,新订阅的观察者能立即拿到这个最新值,完美适配你的场景。
1. 修改共享服务代码
把原来基于EventEmitter的实现改成BehaviorSubject:
import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class FromFloatingButtonToEnvironmentalRiskService { // 初始化一个默认值(比如空字符串) private dateOfSpraySubject = new BehaviorSubject<string>(''); // 对外暴露可观察对象,避免外部直接修改Subject dateOfSpray$ = this.dateOfSpraySubject.asObservable(); // 发射数据的方法 emitOnDataOfSpraySet(date: string) { this.dateOfSpraySubject.next(date); } }
2. 修改floating-button-component.ts
调用服务的emitOnDataOfSpraySet方法不变,保持原有逻辑:
ngOnInit(): void { this.iDatePasser={} as IDatePasser this.iDatePasser.dateOfSpray = ""; const storedDate = localStorage.getItem(environment.keyDateOfSpray); if (storedDate) { this.iDatePasser.dateOfSpray = storedDate; this.isActivateEnvRisk = true; this._FromFloatingButtonToEnvironmentalRiskService.emitOnDataOfSpraySet(this.iDatePasser.dateOfSpray); console.log(this.debugTag, 'this.iDatePasser.dateOfSpray:', this.iDatePasser.dateOfSpray); } }
3. 修改env-risk.ts
订阅服务暴露的dateOfSpray$,订阅后会立即拿到最新的缓存值,同时把后续数据处理逻辑移到订阅回调里,确保拿到有效值再执行:
ngOnInit(): void { this.subEvtEmitter = this._FromFloatingButtonToEnvironmentalRiskService.dateOfSpray$.subscribe((dataOfSpray:string) => { this.dataOfSpray = dataOfSpray; console.log(this.debugTag, ' dataOfSpray:', this.dataOfSpray); // 确保拿到有效值再处理 if(this.dataOfSpray) { this.iEnvRisk.dateOfSpray = this.dataOfSpray; let dateOfSpraySplitted = this.iEnvRisk.dateOfSpray.split("/"); // 其他相关处理逻辑... } }); this.subscriptionCollector.push(this.subEvtEmitter); }
方案二:延迟事件发射时机
如果不想修改服务类型,可以把floating-button里的事件发射延迟到ngAfterViewInit钩子,这个钩子会在所有子组件初始化完成后执行,确保env-risk已经完成订阅:
修改floating-button-component.ts
ngAfterViewInit(): void { this.iDatePasser={} as IDatePasser this.iDatePasser.dateOfSpray = ""; const storedDate = localStorage.getItem(environment.keyDateOfSpray); if (storedDate) { this.iDatePasser.dateOfSpray = storedDate; this.isActivateEnvRisk = true; this._FromFloatingButtonToEnvironmentalRiskService.emitOnDataOfSpraySet(this.iDatePasser.dateOfSpray); console.log(this.debugTag, 'this.iDatePasser.dateOfSpray:', this.iDatePasser.dateOfSpray); } }
注意:如果
env-risk是动态加载的组件,这个方案可能依然失效,所以优先推荐方案一。
内容的提问来源于stack exchange,提问作者Amrmsmb
相关产品推荐
相关产品推荐

