Angular中router.navigate后ngOnInit不执行,新增数据无法实时展示
Angular 新增Firebase数据后列表不自动更新问题
问题描述
我开发了一个简单的Angular应用,其中/personas路径展示Persona对象列表。页面上有一个添加新用户的按钮,点击后跳转到/personas/agregar页面。在该页面可以创建新的Persona对象并提交至Firebase,但提交完成跳转回/personas后,新添加的数据不会自动显示,必须手动刷新页面才会出现。
相关代码
personas.component.ts
export class PersonasComponent implements OnInit { personas: Persona[] = []; constructor(private personasService: PersonasService, private router: Router){} ngOnInit(): void { this.personasService.obtenerPersonas().subscribe( (personas: Persona[]) => { this.personas = personas; this.personasService.setPersonas(personas); } ); } personaAgregada(persona: Persona){ this.personas.push(persona); } agregar(){ this.router.navigate(['personas/agregar']) } }
formulario.component.ts
guardarPersona(){ if(this.id){ this.personasService.modificarPersona(this.id, this.nombreInput, this.apellidoInput); }else{ this.personasService.agregarPersona(new Persona(this.nombreInput, this.apellidoInput)); } this.router.navigate(['personas']); }
persona.service.ts
setPersonas(personas: Persona[]){ this.personas = personas; } obtenerPersonas(){ return this.dataService.cargarPersonas(); } agregarPersona(persona: Persona) { if(this.personas == null){ this.personas = []; } this.personas.push(persona); this.dataService.guardarPersonas(this.personas); }
data.services.ts
cargarPersonas(){ return this.httpClient.get<Persona[]>('https://listado-personas-53faf-default-rtdb.firebaseio.com/personas.json'); } guardarPersonas(personas: Persona[]){ this.httpClient.put(this.url + '.json', personas).subscribe( response => {console.log(`Datos enviados correctamente: ${response}`)}, error => {console.log(`Error al enviar los datos: ${error}`)} ); }
已尝试的无效方案
- 使用NgZone强制更新视图:
this.ngZone.run(() => { this.router.navigateByUrl('personas'); });
- 跳转后重载页面,但导致数据无法提交至Firebase:
this.router.navigate(['personas']).then(() => { window.location.reload(); });
- 监听router.events触发数据刷新,但出现
no overload matches this call错误:
ngOnInit() { this.router.events.subscribe( (event: Event) => { if (event instanceof NavigationEnd) { this.personasService.obtenerPersonas().subscribe( (personas: Persona[]) => { this.personas = personas; this.personasService.setPersonas(personas); } ); } }); }
解决方案
方案1:确保导航在数据提交完成后执行
当前问题核心是guardarPersona中在数据还未提交到Firebase就执行了导航,导致返回列表时新数据还未写入数据库,因此获取不到。需要将导航逻辑放在数据提交的异步回调中:
- 修改
persona.service.ts的agregarPersona方法,返回Observable:
agregarPersona(persona: Persona): Observable<any> { if(this.personas == null){ this.personas = []; } this.personas.push(persona); return this.dataService.guardarPersonas(this.personas); }
- 修改
data.services.ts的guardarPersonas方法,不在内部subscribe,而是返回Observable:
guardarPersonas(personas: Persona[]): Observable<any>{ return this.httpClient.put(this.url + '.json', personas); }
- 修改
formulario.component.ts的guardarPersona方法,等待数据提交完成后再导航:
guardarPersona(){ let obs$: Observable<any>; if(this.id){ obs$ = this.personasService.modificarPersona(this.id, this.nombreInput, this.apellidoInput); }else{ obs$ = this.personasService.agregarPersona(new Persona(this.nombreInput, this.apellidoInput)); } obs$.subscribe({ next: () => this.router.navigate(['personas']), error: (err) => console.error('提交失败:', err) }); }
方案2:在PersonasComponent中正确监听路由激活
修正之前的router.events监听代码,正确处理类型:
import { NavigationEnd, Router } from '@angular/router'; import { filter } from 'rxjs/operators'; // ... ngOnInit(): void { this.loadPersonas(); // 监听路由结束事件,每次回到该组件时重新加载数据 this.router.events.pipe( filter(event => event instanceof NavigationEnd) ).subscribe(() => { this.loadPersonas(); }); } private loadPersonas(): void { this.personasService.obtenerPersonas().subscribe( (personas: Persona[]) => { this.personas = personas; this.personasService.setPersonas(personas); } ); }
方案3:利用BehaviorSubject共享实时数据状态
在服务中使用BehaviorSubject维护personas列表,确保组件能实时获取最新数据:
- 修改
persona.service.ts:
import { BehaviorSubject, Observable, tap } from 'rxjs'; export class PersonasService { private personasSubject = new BehaviorSubject<Persona[]>([]); public personas$ = this.personasSubject.asObservable(); constructor(private dataService: DataService) { // 初始化加载数据 this.dataService.cargarPersonas().subscribe(personas => { this.personasSubject.next(personas); }); } agregarPersona(persona: Persona): Observable<any> { const currentPersonas = this.personasSubject.value; const newPersonas = [...currentPersonas, persona]; return this.dataService.guardarPersonas(newPersonas).pipe( tap(() => this.personasSubject.next(newPersonas)) ); } obtenerPersonas(): Observable<Persona[]> { return this.personas$; } // ...其他方法 }
- 修改
personas.component.ts订阅BehaviorSubject:
ngOnInit(): void { this.personasService.obtenerPersonas().subscribe( (personas: Persona[]) => { this.personas = personas; } ); }
这样添加数据后,服务会立即更新Subject的值,组件能自动收到最新列表,无需刷新。
内容的提问来源于stack exchange,提问作者Manu
相关产品推荐
相关产品推荐

