You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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就执行了导航,导致返回列表时新数据还未写入数据库,因此获取不到。需要将导航逻辑放在数据提交的异步回调中:

  1. 修改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);
  }
  1. 修改data.services.ts的guardarPersonas方法,不在内部subscribe,而是返回Observable:
guardarPersonas(personas: Persona[]): Observable<any>{
    return this.httpClient.put(this.url + '.json', personas);
}
  1. 修改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列表,确保组件能实时获取最新数据:

  1. 修改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$;
  }

  // ...其他方法
}
  1. 修改personas.component.ts订阅BehaviorSubject:
ngOnInit(): void {
  this.personasService.obtenerPersonas().subscribe(
    (personas: Persona[]) => {
      this.personas = personas;
    }
  );
}

这样添加数据后,服务会立即更新Subject的值,组件能自动收到最新列表,无需刷新。


内容的提问来源于stack exchange,提问作者Manu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:25:28