Angular 5:如何在路由守卫中传递获取的数据至目标组件?
Great question! You’re right to suspect that Resolve guards are exactly the tool you need here—they’re designed specifically for pre-fetching data before a route activates and passing that data directly to the target component, which avoids duplicate API calls and fits perfectly with your low-complexity app requirements.
Why Your Original CanActivate Approach Failed
The reason setting next.data.client = data in your CanActivate guard didn’t work is because the ActivatedRouteSnapshot passed to canActivate is immutable. Any modifications you make to it won’t propagate to the component’s ActivatedRoute instance, so the data never reaches your ClientDetail component.
Step-by-Step Implementation
1. Convert Your Guard to a Resolver
Rename your guard (for clarity) and implement Angular’s Resolve interface. This guard will return the fetched client data instead of a boolean, and handle errors by redirecting if the API call fails.
import { Injectable } from '@angular/core'; import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; import { Observable, of } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { ClientService } from './path-to-your-client-service'; import { Client } from './path-to-your-client-model'; // Adjust to your actual Client type @Injectable() export class ClientDetailResolver implements Resolve<Client> { constructor( private clientService: ClientService, private router: Router ) {} resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Client> { const clientId = route.params.id; return this.clientService.get(clientId).pipe( catchError((err) => { // Redirect to a safe page (e.g., client list) if the client doesn't exist this.router.navigate(['/clients']); return of(null); }) ); } }
2. Update Your Route Configuration
Replace the canActivate property with resolve, and map your resolver to a key (this key will be used to access the data in the component).
{ path: ':id', resolve: { client: ClientDetailResolver // This key defines how you'll fetch the data in the component }, component: ClientDetail }
3. Access the Data in ClientDetail Component
Retrieve the pre-fetched client data from the route’s data property. Use snapshot if the route parameters won’t change while the component is active, or subscribe if you need to handle dynamic parameter updates.
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Client } from './path-to-your-client-model'; @Component({ selector: 'app-client-detail', templateUrl: './client-detail.component.html' }) export class ClientDetail implements OnInit { client: Client; constructor(private route: ActivatedRoute) {} ngOnInit(): void { // For static route parameters this.client = this.route.snapshot.data['client']; // For dynamic parameter changes (e.g., navigating to another client from this component) // this.route.data.subscribe(data => { // this.client = data['client']; // }); } }
Why This Works
- Resolvers are purpose-built for this exact use case: fetching data before a route loads and injecting it into the route’s data.
- No extra state containers or shared services are needed, keeping your code lean for a low-complexity app.
- You avoid duplicate API calls since the data is fetched once in the resolver and passed directly to the component.
内容的提问来源于stack exchange,提问作者Christian Benseler

