Angular5路由后数据丢失求助:组件间传值失败
解决Angular组件间路由后数据丢失的问题
看起来你遇到的核心问题是组件间数据共享的时机不对,加上可能存在服务实例不唯一的问题,导致路由到StudentComponent后拿到的是undefined。我来一步步帮你解决:
问题分析
- 数据存储时机错误:你现在是在
FormComponent的ngOnDestroy钩子中把值存到DataService,但这个钩子是组件销毁时才触发的。如果用户是点击按钮生成res后立即路由跳转,可能ngOnDestroy执行时res还没完成赋值,或者路由跳转的逻辑已经先走了,导致服务里没拿到正确的值。 - 服务实例不唯一:如果你的
DataService没有被设置为单例(比如在每个组件的providers数组里声明),那么FormComponent和StudentComponent会各自创建一个服务实例,数据自然无法共享。 - 无用的初始化代码:
FormComponent构造函数里的this.newVal = this.res完全没用,因为此时res还没有被赋值。
解决方案
第一步:确保DataService是单例
修改dataservice.ts,添加@Injectable装饰器并设置providedIn: 'root',这样Angular会在整个应用中提供同一个服务实例:
// dataservice.ts import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' // 关键:确保服务是单例 }) export class DataService { public link: any; public test: string; }
⚠️ 注意:不要在任何组件的@Component装饰器的providers数组里添加DataService,否则会覆盖单例,创建新的实例。
第二步:在生成数据时立即同步到服务
把FormComponent中存储数据的逻辑从ngOnDestroy移到sendValues方法里,这样生成res后立刻把值存到服务:
// forms.component.ts import { Component, OnInit, OnDestroy } from '@angular/core'; import { NgForm } from '@angular/forms'; import { DataService } from '../dataservice'; @Component({ selector: 'app-form', templateUrl: './form.component.html', styleUrls: ['./form.component.css'] }) export class FormComponent implements OnInit, OnDestroy { name = 'kanav'; link = ''; res: string; str: string; newVal: any; constructor(public dataservice: DataService) { // 删掉无用的this.newVal = this.res } ngOnInit() { } ngOnDestroy() { // 这里不需要再存数据了 } sendValues(): void { this.res = this.str.substring(0, this.str.length - 11) + 'embedded=true'; console.log(this.res); // 生成数据后立即同步到服务 this.dataservice.link = this.res; this.dataservice.test = this.name; } }
第三步:优化StudentComponent的数据获取(可选但推荐)
如果想让StudentComponent能实时响应数据变化(比如用户在FormComponent中多次修改值),可以用RxJS的BehaviorSubject来实现响应式数据传递,这是Angular中组件间数据共享的最佳实践之一:
更新DataService:
// dataservice.ts import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class DataService { // 用BehaviorSubject存储数据,支持订阅和实时更新 private linkSubject = new BehaviorSubject<any>(null); public link$ = this.linkSubject.asObservable(); // 暴露可观察对象给组件 private testSubject = new BehaviorSubject<string>(''); public test$ = this.testSubject.asObservable(); // 提供设置数据的方法 setLink(link: any) { this.linkSubject.next(link); } setTest(test: string) { this.testSubject.next(test); } }
更新FormComponent的sendValues方法:
sendValues(): void { this.res = this.str.substring(0, this.str.length - 11) + 'embedded=true'; console.log(this.res); this.dataservice.setLink(this.res); this.dataservice.setTest(this.name); }
更新StudentComponent:
// student.component.ts import { Component, OnInit, OnDestroy } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import { DataService } from '../dataservice'; import { Subscription } from 'rxjs'; @Component({ selector: 'app-student', templateUrl: './student.component.html', styleUrls: ['./student.component.css'] }) export class StudentComponent implements OnInit, OnDestroy { finalVal: any; finaltest: string; private subscriptions = new Subscription(); // 管理订阅,防止内存泄漏 constructor( public sanitizer: DomSanitizer, public dataservice: DataService ) { } ngOnInit() { // 订阅数据变化,自动更新组件内的变量 this.subscriptions.add( this.dataservice.link$.subscribe(link => { this.finalVal = link; }) ); this.subscriptions.add( this.dataservice.test$.subscribe(test => { this.finaltest = test; }) ); } ngOnDestroy() { // 销毁所有订阅,避免内存泄漏 this.subscriptions.unsubscribe(); } show() { console.log(this.finaltest); console.log(this.finalVal); } }
为什么这样能解决问题?
- 单例服务确保了
FormComponent和StudentComponent操作的是同一个数据容器。 - 在
sendValues中立即存储数据,保证了路由跳转前数据已经被正确写入服务。 - 用
BehaviorSubject实现响应式数据传递,不仅能解决当前的路由后数据丢失问题,还能支持后续的数据实时更新场景。
内容的提问来源于stack exchange,提问作者Kanav Malik
相关产品推荐
相关产品推荐

