5

如何从父路由的守卫重定向到子路由,同时保护子路由不被直接访问*?

绝对导航的问题,当导航到子路由时,父组件上的守卫会在循环中再次调用。

相对导航的问题是守卫正在保护父路由,因此还没有激活的路由可以相对导航。此外,这可能不会保护子路由。也许同样的守卫也可以用于子路由或 CanActivateChildren。

Stackblitz 示例:https ://stackblitz.com/edit/angular-qbe2a7

路线

const appRoutes: Routes = [
  {
    path: 'foo',
    component: FooComponent,
    canActivate: [ RedirectionGuard ],
    children: [
      {
        path: 'foo-child',
        component: FooChildComponent
      }
    ]
  }
];

canActivate() 在守卫中

canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean>|Promise<boolean>|boolean {

    console.log('guard: ', route, state, this.route);

    // idea: create own ActivatedRoute and give it the values from ActivatedRouteSnapshot which knows about 'foo/'
    const foo: ActivatedRoute = new ActivatedRoute();
    console.log(foo);

    // Error: Cannot match any routes
    // I think because there is no route to be relative to when canActivat is called. Router has not yet navigated to '/foo/'
    this.router.navigate(['../foo-child'], {               relativeTo: this.route
    });

    // Errors with infinite loop because '/foo/' has this guard which will then be called again
    //this.router.navigate(['/foo/foo-child']);

    // navigate returns true also. maybe just return that.
    return true;
  }

*为什么不为您可能要求的所有孩子添加警卫。我需要根据应用程序的状态从父路由重定向到许多不同的子路由。我目前正在使用其中一个子路由从该组件重定向,但这并不能保护子路由形成用户直接导航。

4

1 回答 1

2

实现此目的的一种方法是使用 url 参数,在进入父路由时使用 canActivateChild 和 redirectTo 子路由。

StackBlitz 示例:https ://stackblitz.com/edit/angular-redirect-with-params

路由

const appRoutes: Routes = [
  {
    path: 'foo',
    component: FooComponent,
    canActivateChild: [ RedirectionGuard ],
    children: [
      {
        path: '',
        pathMatch: 'full',
        redirectTo: 'foo-child-1'
      },
      {
        path: 'foo-child-1',
        component: FooChildComponent
      },
       {
        path: 'foo-child-2',
        component: FooChildComponent
      }
    ]
  },
];

警卫

canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean>|Promise<boolean>|boolean {

    console.log('params:', route.params, route.url);
    if (!route.params.skip) {
      this.router.navigate(['/foo/foo-child-2', { skip: true }], {
        queryParams: { skip: 1 }
      });
    }

    return true;

  }

  canActivateChild(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ) {
    return this.canActivate(route, state);
  }
于 2018-09-26T14:02:02.487 回答