Angular4 路由:绕过路由守卫强制导航

Posted

技术标签:

【中文标题】Angular4 路由:绕过路由守卫强制导航【英文标题】:Angular4 Routing: Force Navigation By Bypassing Route Guard 【发布时间】:2017-10-01 16:36:32 【问题描述】:

当我的用户在屏幕上发生脏更改时,我有一个路由守卫在他们尝试导航离开时提示他们保存或丢弃。

但是,如果我因为不活动而将它们注销,我想强制导航并绕过路由守卫(通过丢弃它们的更改),以确保它们的屏幕是空白的。

如何绕过路线守卫?

【问题讨论】:

【参考方案1】:

我创建了一个类似白名单的东西来写下我想绕过守卫的每条路线

white-list.ts

export const WhiteListedRoutes: string[] = [
  '/route1',
  '/route2',
];

然后在守卫中类似:

import  WhiteListedRoutes  from './white-list';

@Injectable(
  providedIn: 'root'
)
export class AuthGuard implements CanActivate 
  constructor(private authService: AuthService, private router: Router) 

  canActivate(_next: ActivatedRouteSnapshot, _state: RouterStateSnapshot): boolean | Promise<boolean> 
    const route = state.url.split('?')[0];
    const queryParams = _route.queryParams;
    const isWhiteListed = WhiteListedRoutes.findIndex((r: string) => r === route) >= 0;

    return this.status || isWhiteListed || this.router.navigate(['/'],  state:  r: route , queryParams  );
  

【讨论】:

【参考方案2】:

您可以通过以下方式强制绕过每个导航。在我的情况下,我在用户提交包含帐户信息的表单后导航回帐户仪表板。

理想情况下,您会检查表单中未保存的更改并据此绕过,但我的表单还没有该功能。

表单组件:

this.router.navigateByUrl('/',  state:  bypassFormGuard: true  )

路由器保护:

@Injectable()
export class ExitFormGuard implements CanDeactivate<ComponentCanDeactivate> 

   constructor(private router: Router) 

   canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> 
      if (this.router.getCurrentNavigation()?.extras?.state?.bypassFormGuard) 
         return true
      

      // perform normal checks
   


【讨论】:

谢谢,这是个好主意,但可以通过使用可选链接和 ? 来缩短它。 developer.mozilla.org/en-US/docs/Web/javascript/Reference/… if (navObject?.extras?.state?.bypassFormGuard) return true; @Pierre 好点,我更新了答案【参考方案3】:

我的解决方案如下:

我的logout方法在成功登出后,将应用重定向到/login路由:

@Injectable
export class AuthService 
  // ...
  logout () 
    // do logout
    this.router.navigate(['/login']);
  

那么我的守卫如下:

@Injectable
export class DiscardChangesGuard implements CanDeactivate<MyComponent> 

  canDeactivate(component: MyComponent, currentRoute: ActivatedRouteSnapshot,
                currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): Observable<boolean> | boolean 

    if (nextState.url === '/login') 
      return true; // bypass checks if we are trying to go to /login
    

    // perform regular checks here
  

【讨论】:

【参考方案4】:

我的目标是绕过路线守卫而不触及应用程序中的每个路线守卫,但我无法做到。最终我创建了一个新的RouteBypassService 注入到每个路由守卫中。 RouteBypassService 实现 shouldBypass,如果路由守卫应该允许导航出于某些覆盖带外原因(例如授权),则返回 true。在我的情况下,shouldBypass 在没有用户登录的情况下返回 true。(在他们退出后,我们无论如何都让他们离开屏幕)。

不是很理想,因为每一个路由守卫的作者都要肯定记得加旁路,但也不是很纠结。

【讨论】:

以上是关于Angular4 路由:绕过路由守卫强制导航的主要内容,如果未能解决你的问题,请参考以下文章

路由导航守卫(导航钩子)

Vue路由守卫详解

VueRouter-导航守卫路由守卫

Vue 导航守卫

路由拦截方式 全局守卫导航

路由导航守卫