Angular2/4中ngFor结合routerLink使用浏览器返回按钮渲染异常问题
Hey there! Let's figure out why your Angular component's ngFor isn't rendering after using the browser back button. This is a common gotcha with Angular routing + Firestore, so let's break down the likely causes and fixes:
1. Your component is being reused by Angular's default routing strategy
Angular reuses route components when navigating back to avoid reinitializing them. That means if you only fetch Firestore data in ngOnInit(), it won't run again when you return—so your data stays stale (or empty if it loaded asynchronously after the first init).
Fix: Listen for route navigation events to reload data
Add a listener to detect when you navigate back to this component, then re-fetch your Firestore data. Here's how:
import { Component, OnInit, OnDestroy } from '@angular/core'; import { AngularFirestore } from '@angular/fire/compat/firestore'; import { Router, NavigationEnd } from '@angular/router'; import { Subscription } from 'rxjs'; import { filter } from 'rxjs/operators'; @Component({ selector: 'app-class', templateUrl: './class.component.html' }) export class ClassComponent implements OnInit, OnDestroy { classes: any[] = []; private routerSubscription: Subscription | undefined; private firestoreSubscription: Subscription | undefined; constructor( private firestore: AngularFirestore, private router: Router ) {} ngOnInit(): void { this.loadClasses(); // Watch for navigation back to this component this.routerSubscription = this.router.events .pipe(filter(event => event instanceof NavigationEnd)) .subscribe(() => { // Check if we're on the class component route if (this.router.url === '/your-class-route-path') { this.loadClasses(); } }); } private loadClasses(): void { // Clean up old subscription first to prevent memory leaks this.firestoreSubscription?.unsubscribe(); // Fetch fresh data from Firestore this.firestoreSubscription = this.firestore.collection('your-collection-name') .valueChanges({ idField: 'id' }) // Include document ID if needed .subscribe(classes => { this.classes = classes; }); } ngOnDestroy(): void { // Clean up subscriptions when component is destroyed this.routerSubscription?.unsubscribe(); this.firestoreSubscription?.unsubscribe(); } }
2. You're not using Angular's async pipe (the easiest fix!)
The async pipe is Angular's built-in way to handle observable data—it automatically subscribes/unsubscribes and triggers change detection. If you're manually subscribing and storing data in a property, the change detector might not pick up the update when you navigate back.
Fix: Switch to the async pipe
Rewrite your component to use an observable with the async pipe in the template:
// class.component.ts import { Component } from '@angular/core'; import { AngularFirestore } from '@angular/fire/compat/firestore'; import { Observable } from 'rxjs'; @Component({ selector: 'app-class', templateUrl: './class.component.html' }) export class ClassComponent { // Define an observable for your Firestore data classes$: Observable<any[]>; constructor(private firestore: AngularFirestore) { // Fetch data as an observable this.classes$ = this.firestore.collection('your-collection-name') .valueChanges({ idField: 'id' }); } }
Then update your template:
<!-- class.component.html --> <div *ngFor="let cls of classes$ | async" [routerLink]="['/classlist', cls.id]"> {{ cls.name }} <!-- Replace with your actual data properties --> </div>
This is the most recommended approach because it eliminates manual subscription management and ensures change detection works correctly when navigating back.
3. Change detection isn't triggering
If your data is updating but the template isn't reflecting it, Angular's change detector might not be running. While manually triggering it is a last resort, you can try it if the above fixes don't work:
import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; import { AngularFirestore } from '@angular/fire/compat/firestore'; @Component({ selector: 'app-class', templateUrl: './class.component.html' }) export class ClassComponent implements OnInit { classes: any[] = []; constructor( private firestore: AngularFirestore, private cdr: ChangeDetectorRef ) {} ngOnInit(): void { this.firestore.collection('your-collection-name') .valueChanges({ idField: 'id' }) .subscribe(classes => { this.classes = classes; // Manually trigger change detection this.cdr.detectChanges(); }); } }
But again, the async pipe is better because it handles this automatically.
Quick checks to rule out other issues
- Open your browser's developer tools (Console tab) to see if there are any errors related to Firestore permissions, subscriptions, or routing.
- Verify that your Firestore collection has data and the subscription is actually emitting values when you navigate back.
内容的提问来源于stack exchange,提问作者tru

