Angular路由守卫中如何传递布尔参数?优化路由校验逻辑
Got it, let's refactor this to make your route guard way more efficient by using those boolean flags directly instead of looping through a Map every time. Here's a step-by-step solution that fits your requirement:
First, we'll streamline the service to properly manage those boolean activation flags, ensure configs load only once, and make the flags easy to access. We'll also ditch that arbitrary waitSecond delay—instead, we'll wait for the config to actually load before checking flags.
import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { Observable, of } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class RouteActivationService { // Store all page activation flags in a typed object for O(1) access pageFlags: Record<string, boolean> = { [Names.HOME]: false, // Add other page names here as needed (e.g., [Names.PROFILE]: false) }; private configsLoaded = false; constructor(private router: Router) {} // Load configs once and initialize flags loadConfigs(): Observable<void> { if (this.configsLoaded) return of(); // Skip if already loaded return this.getUIConfigurations().pipe( tap(configs => { // Reset all flags to false first Object.keys(this.pageFlags).forEach(key => this.pageFlags[key] = false); // Set flags based on fetched configs configs.names.forEach(config => { if (this.pageFlags.hasOwnProperty(config.name)) { this.pageFlags[config.name] = true; } }); this.configsLoaded = true; }) ); } // Get activation status for a specific page isPageActive(pageName: string): boolean { return this.pageFlags[pageName] || false; } // Guard logic to check activation and redirect if needed async checkActivation(pageName: string): Promise<boolean> { await this.loadConfigs().toPromise(); // Wait for configs to load if (this.isPageActive(pageName)) { return true; } else { this.router.navigateByUrl('/page_not_found'); return false; } } // Your existing config fetch method (keep this as-is) private getUIConfigurations(): Observable<any> { // Replace with your actual config API call return of({ names: [{ name: Names.HOME, secondary_tabs: [] }] }); } }
Now update the ActivateRoutes guard to use the service's precomputed boolean flags instead of checking the Map every time:
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot } from '@angular/router'; import { RouteActivationService } from './route-activation.service'; @Injectable({ providedIn: 'root' }) export class ActivateRoutes implements CanActivate { constructor(private activationService: RouteActivationService) {} async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> { // Grab the page name from route data (same as before) const pageName = route.data.name as string; // Use the service's precomputed flag instead of Map lookup return this.activationService.checkActivation(pageName); } }
Your existing route setup stays almost identical—we still use the data.name field to map routes to their flags:
{ path: 'home', loadChildren: 'src/app/home/home.module#HomeModule', data: { title: 'Home', name: Names.HOME }, canActivate: [ActivateRoutes] }
If you want to skip the data.name mapping entirely and reference the boolean flag directly in route config, you can adjust the guard to check based on the route path instead:
// Update canActivate in ActivateRoutes async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> { await this.activationService.loadConfigs().toPromise(); switch(route.routeConfig?.path) { case 'home': return this.activationService.pageFlags[Names.HOME]; // Add cases for other routes default: this.router.navigateByUrl('/page_not_found'); return false; } }
This lets you remove the data.name field from your route config entirely, making the guard even faster.
- O(1) Access: No more looping through a Map every time the guard runs—we just access a precomputed boolean directly
- Config Caching: Configs load once, not every time the guard is triggered
- Reliable Async: We wait for configs to actually load instead of using a random delay, so flags are always accurate
内容的提问来源于stack exchange,提问作者Hans

