Winkel 9. Starten Sie die aktuellen Seitenschutzvorrichtungen neu. Lösen Sie aktuelle Routenwächter aus

Angesichts der Notwendigkeit, die Schutzvorrichtungen für die aktuelle Seite neu zu starten, unabhängig davon, welche Seite geöffnet ist.



Ich habe keine Standardlösung gefunden, und die im Internet angebotenen sind auf eine Seite beschränkt. Deshalb habe ich mein eigenes geschrieben und beschlossen, es zu teilen.



Fallschilderung



Bewerbungsseiten sind in 3 Gruppen unterteilt:



  • Nur für autorisierte Benutzer

  • Nur für nicht autorisierte Benutzer

  • Für alle Benutzer



Sie können sich auf jeder Seite an- oder abmelden.



Wenn Sie eine Seite mit eingeschränktem Zugriff betreten / verlassen, müssen Sie zur zulässigen Seite wechseln.



Wenn die Seite keine Einschränkungen aufweist, müssen Sie auf der aktuellen Seite bleiben.



Zum besseren Verständnis ist es ratsam zu wissen über:



  • Wache - Kann aktivieren

  • Route

  • Router

  • ActivatedRoute

  • Router-Steckdose



Entscheidung



Die Differenzierung der Zugriffsrechte auf Seiten erfolgt durch guard - CanActivate. Die Überprüfung wird ausgeführt, wenn Sie zur Seite gehen, reagiert jedoch nicht auf Änderungen der Rechte, wenn der Übergang bereits erfolgt ist. Um Doppellogik für Zugriffsrechte zu vermeiden, starten wir die Wachen zwangsweise neu.



Das Neustarten der Schutzvorrichtungen für die aktuelle Seite erfolgt durch Navigieren in der aktuellen URL. Und Änderungen an den Strategien Router.onSameUrlNavigation und Route.runGuardsAndResolvers.



Hier ist eine fertige Lösung. Weitere Details im nächsten Abschnitt.
  import { Injectable } from '@angular/core';
  import { ActivatedRoute, PRIMARY_OUTLET, Router, RunGuardsAndResolvers } from '@angular/router';

  @Injectable()
  export class GuardControlService {
    constructor(
      private route: ActivatedRoute,
      private router: Router,
    ) {}

    /**
    *   guard-  url
    */
    forceRunCurrentGuards(): void {
      //   Router.onSameUrlNavigation       url
      const restoreSameUrl = this.changeSameUrlStrategy(this.router, 'reload');

      //   ActivatedRoute  primary outlet
      const primaryRoute: ActivatedRoute = this.getLastRouteForOutlet(this.route.root, PRIMARY_OUTLET);

      //   runGuardsAndResolvers  ActivatedRoute          url
      const restoreRunGuards = this.changeRunGuardStrategies(primaryRoute, 'always');

      //   
      this.router.navigateByUrl(
        this.router.url
      ).then(() => {
        //  onSameUrlNavigation
        restoreSameUrl();
        //  runGuardsAndResolvers
        restoreRunGuards();
      });
    }

    /**
    *  onSameUrlNavigation    
    * @param router - Router,    
    * @param strategy -  
    * @return callback   
    */
    private changeSameUrlStrategy(router: Router, strategy: 'reload' | 'ignore'): () => void {
      const onSameUrlNavigation = router.onSameUrlNavigation;
      router.onSameUrlNavigation = strategy;

      return () => {
        router.onSameUrlNavigation = onSameUrlNavigation;
      }
    }

    /**
    *   route  outlet-
    * @param route - Route    
    * @param outlet -  outlet-,    
    * @return  ActivatedRoute   outlet
    */
    private getLastRouteForOutlet(route: ActivatedRoute, outlet: string): ActivatedRoute {
      if (route.children?.length) {
        return this.getLastRouteForOutlet(
          route.children.find(item => item.outlet === outlet),
          outlet
        );
      } else {
        return route;
      }
    }

    /**
    *  runGuardsAndResolvers  ActivatedRoute   ,    
    * @param route - ActivatedRoute    
    * @param strategy -  
    * @return callback   
    */
    private changeRunGuardStrategies(route: ActivatedRoute, strategy: RunGuardsAndResolvers): () => void {
      const routeConfigs = route.pathFromRoot
        .map(item => {
          if (item.routeConfig) {
            const runGuardsAndResolvers = item.routeConfig.runGuardsAndResolvers;
            item.routeConfig.runGuardsAndResolvers = strategy;
              return runGuardsAndResolvers;
              } else {
            return null;
          }
        });

      return () => {
        route.pathFromRoot
          .forEach((item, index) => {
            if (item.routeConfig) {
              item.routeConfig.runGuardsAndResolvers = routeConfigs[index];
            }
          });
      }
    }
  }
  




Zusätzliche Lösungsbeschreibung



Das erste, was Sie versuchen möchten, um die Wachen neu zu starten, ist die Navigation zur aktuellen URL.



this.router.navigateByUrl(this.router.url);


Standardmäßig wird das aktuelle URL-Übergangsereignis jedoch ignoriert und es passiert nichts. Damit dies funktioniert, müssen Sie das Routing konfigurieren.



Routing einrichten



1. Ändern Sie die Router-Strategie. onSameUrlNavigation



onSameUrlNavigation kann die folgenden Werte annehmen:



onSameUrlNavigation: 'reload' | 'ignore';


Um die Empfindlichkeit für den Übergang zur aktuellen URL zu gewährleisten, müssen Sie "Neu laden" festlegen.



Die Richtlinienänderung wird nicht neu geladen, sondern generiert ein zusätzliches Navigationsereignis. Es kann über ein Abonnement erhalten werden:



this.router.events.subscribe();


2. Ändern Sie die Routenstrategie. runGuardsAndResolvers



runGuardsAndResolvers kann die folgenden Werte annehmen:



type RunGuardsAndResolvers = 'pathParamsChange' | 'pathParamsOrQueryParamsChange' | 'paramsChange' | 'paramsOrQueryParamsChange' | 'always' | ((from: ActivatedRouteSnapshot, to: ActivatedRouteSnapshot) => boolean);


Um die Empfindlichkeit für den Übergang zur aktuellen URL zu gewährleisten, müssen Sie "immer" festlegen.



Konfigurieren des Routings während der Anwendungskonfiguration



onSameUrlNavigation:



const routes: : Route[] = [];
@NgModule({
  imports: [
    RouterModule.forRoot(
      routes,
      { onSameUrlNavigation: 'reload' }
    )
  ]
})


runGuardsAndResolvers:



const routes: Route[] = [
  {
    path: '',
    component: AppComponent,
    runGuardsAndResolvers: 'always',
  }
];


Routing zur Laufzeit konfigurieren



constructor(
  private router: Router,
  private route: ActivatedRoute
) {
  this.router.onSameUrlNavigation = 'reload';
  this.route.routeConfig.runGuardsAndResolvers = 'always';
}


Wachen neu starten



Um die Schutzvorrichtungen einer bestimmten Seite neu zu starten, reicht es aus, das Routing während der Konfiguration zu konfigurieren.



Wenn Sie jedoch die Wachen einer Seite neu laden, führt das Ändern von runGuardsAndResolvers in jeder Route zu unnötigen Überprüfungen. Und die Notwendigkeit, sich immer an diesen Parameter zu erinnern - an Fehler.



Da in unserem Fall ein Neustart für jede Seite ohne Einschränkungen beim Einrichten der Anwendung vorausgesetzt wird, benötigen Sie:



1. Ersetzen Sie onSameUrlNavigation und behalten Sie den aktuellen Wert bei



//   Router.onSameUrlNavigation       url
const restoreSameUrl = this.changeSameUrlStrategy(this.router, 'reload');

...
/**
*  onSameUrlNavigation    
* @param router - Router,    
* @param strategy -  
* @return callback   
*/
private changeSameUrlStrategy(router: Router, strategy: 'reload' | 'ignore'): () => void {
  const onSameUrlNavigation = router.onSameUrlNavigation;
  router.onSameUrlNavigation = strategy;

  return () => {
    router.onSameUrlNavigation = onSameUrlNavigation;
  }
}


2. Holen Sie sich ActivatedRoute für die aktuelle URL



Da die Injektion ActivatedRoute im Dienst ausgeführt wird, ist die resultierende ActivatedRoute nicht mit der aktuellen URL verknüpft.



ActivatedRoute für die aktuelle URL befindet sich in der letzten primären Steckdose und muss gefunden werden:



//   ActivatedRoute  primary outlet
const primaryRoute: ActivatedRoute = this.getLastRouteForOutlet(this.route.root, PRIMARY_OUTLET);

...
/**
*   route  outlet-
* @param route - Route    
* @param outlet -  outlet-,    
* @return  ActivatedRoute   outlet
*/
private getLastRouteForOutlet(route: ActivatedRoute, outlet: string): ActivatedRoute {
  if (route.children?.length) {
    return this.getLastRouteForOutlet(
      route.children.find(item => item.outlet === outlet),
      outlet
   );
  } else {
    return route;
  }
}


3. Ersetzen Sie runGuardsAndResolvers für alle ActivatedRoute und ihre Vorfahren, wobei Sie die aktuellen Werte beibehalten



Eine Wache, die den Zugriff einschränkt, kann sich in einem der Vorfahren der aktuellen ActivatedRoute befinden. Alle Vorfahren befinden sich in pathFromRoot.



//   runGuardsAndResolvers  ActivatedRoute          url
const restoreRunGuards = this.changeRunGuardStrategies(primaryRoute, 'always');

...
/**
*  runGuardsAndResolvers  ActivatedRoute   ,    
* @param route - ActivatedRoute    
* @param strategy -  
* @return callback   
*/
private changeRunGuardStrategies(route: ActivatedRoute, strategy: RunGuardsAndResolvers): () => void {
  const routeConfigs = route.pathFromRoot
    .map(item => {
      if (item.routeConfig) {
        const runGuardsAndResolvers = item.routeConfig.runGuardsAndResolvers;
        item.routeConfig.runGuardsAndResolvers = strategy;
        return runGuardsAndResolvers;
      } else {
        return null;
      }
    });

  return () => {
    route.pathFromRoot
      .forEach((item, index) => {
        if (item.routeConfig) {
          item.routeConfig.runGuardsAndResolvers = routeConfigs[index];
        }
      });
  }
}


4. Gehen Sie zur aktuellen URL



this.router.navigateByUrl(this.router.url);


5. Setzen Sie runGuardsAndResolvers und onSameUrlNavigation auf ihren ursprünglichen Zustand zurück



restoreRunGuards();
restoreSameUrl();


6. Kombinieren Sie Stufen in einer Funktion



constructor(
  private route: ActivatedRoute,
  private router: Router,
) {}

/**
*   guard-  url
*/
forceRunCurrentGuards(): void {
  //   Router.onSameUrlNavigation       url
  const restoreSameUrl = this.changeSameUrlStrategy(this.router, 'reload');

  //   ActivatedRoute  primary outlet
  const primaryRoute: ActivatedRoute = this.getLastRouteForOutlet(this.route.root, PRIMARY_OUTLET);

  //   runGuardsAndResolvers  ActivatedRoute          url
  const restoreRunGuards = this.changeRunGuardStrategies(primaryRoute, 'always');

  //   
  this.router.navigateByUrl(
    this.router.url
  ).then(() => {
    //  onSameUrlNavigation
    restoreSameUrl();
    //  runGuardsAndResolvers
    restoreRunGuards();
  });
}





Ich hoffe, dieser Artikel hat Ihnen geholfen. Wenn es andere Lösungen gibt, würde ich mich freuen, sie in den Kommentaren zu sehen.



All Articles