简体   繁体   English

使用 canActivate 防护时 redirectTo 不起作用

[英]redirectTo not working when using canActivate guard

The redirectTo property isn't working in my Angular 2 app. redirectTo属性在我的 Angular 2 应用程序中不起作用。 I have the following routes in my app.routing.ts :我的app.routing.ts有以下路线:

const routes: Routes = [
  { path: '', redirectTo: '/page/1', pathMatch: 'full' },
  { path: 'page', loadChildren: 'app/modules/page/page.module#PageModule' }
]

export const routing = RouterModule.forRoot(routes);

Then, in my page.routing.ts , I have the following:然后,在我的page.routing.ts ,我有以下内容:

const pageRoutes: Routes = [
  { path: ':id', component: PageComponent, canActivate: [LoginGuard] }
];

export const pageRouting = RouterModule.forChild(pageRoutes);

Every time I access the home page it displays the LoginComponent for a second, then it disappears.每次我访问主页时,它都会显示LoginComponent一秒钟,然后消失。 However, it should redirect to the PageComponent .但是,它应该重定向到PageComponent

Why isn't that happening?为什么没有发生这种情况? Why the LoginComponent is being loaded (even if it's only for a brief second) if the user is already logged in?如果用户已经登录,为什么要加载LoginComponent (即使它只是短暂的一秒钟)?

Here's my LoginGuard :这是我的LoginGuard

@Injectable()
export class LoginGuard implements CanActivate {

  constructor(private af: AngularFire, private router: Router) {}

  canActivate(): Observable<boolean> {
    return this.af.auth.map(auth =>  {
      if (auth === null) {
        this.router.navigate(['/login']);
        return false;
      } else {
        return true;
      }
    }).first();
  }

}

EDIT: Temporarily, I changed the LoginComponent to redirect to the PageComponent if a user is logged in. I still wonder, though, why redirectTo isn't working.编辑:暂时,如果用户登录,我将LoginComponent更改为重定向到PageComponent 。不过,我仍然想知道为什么redirectTo不起作用。

I don't know exactly why this is happening, but I believe if you check the LoginGuard before the PageModule loads, it will work. 我不知道为什么会这样,但是我相信如果在PageModule加载之前检查LoginGuard,它将起作用。

app.routing.ts 应用程序路由

const routes: Routes = [
  { path: '', redirectTo: '/page/1', pathMatch: 'full' },
  { 
    path: 'page', 
    // Call the guard before the module is loaded
    canLoad: [ LoginGuard ]
    loadChildren: 'app/modules/page/page.module#PageModule' 
  }
]

export const routing = RouterModule.forRoot(routes);

LoginGuard LoginGuard

@Injectable()
export class LoginGuard implements CanActivate, CanLoad {

  constructor(private af: AngularFire, private router: Router) {}

  // Add this method to validade the canLoad
  canLoad(route: Route): Observable<boolean> {
    return this.canActivate();
  }  

  canActivate(): Observable<boolean> {
    return this.af.auth.map(auth =>  {
      if (auth === null) {
        this.router.navigate(['/login']);
        return false;
      } else {
        return true;
      }
    }).first();
  }

}

This is happening because you call this.router.navigate(['/login']);这是因为你调用this.router.navigate(['/login']); directly from your route guard which initializes a new route navigation on top of the one currently running.直接来自您的路线守卫,它会在当前运行的路线上初始化一个新的路线导航。 You create a "race" between two navigations;您在两个导航之间创建了“竞赛”; my guess is the one to /login' wins because the other one has to lazy load the module (takes some time).我的猜测是/login'获胜,因为另一个必须延迟加载模块(需要一些时间)。 But after the loading is done, it changes to that route afterwards, hence the "flashing" login popup.但是加载完成后,它会更改为该路由,因此“闪烁”登录弹出窗口。

You should NOT navigate inside a Guard, instead you should always return either a boolean (to allow navigate true/false) or a UrlTree if you want to redirect/change the route.您不应该在 Guard 内导航,相反,如果您想重定向/更改路线,您应该始终返回boolean (以允许导航真/假)或UrlTree The Guard returns the value and the router will then change navigation to the provided UrlTree for you inside the ongoing/triggered navigation and you won't get any race. Guard 返回该值,然后路由器将在正在进行的/触发的导航中将导航UrlTree为为您提供的UrlTree ,您将不会遇到任何竞争。

So change your method like this, and it will work correct.所以像这样改变你的方法,它会正常工作。

canActivate(): Observable<boolean|UrlTree> {
  return this.af.auth.map(auth =>  {
    if (auth === null) {
      return this.router.parseUrl('/login');
    }
    return true;
  }).first();
}

You should see it like this, if you would call this.router.navigate in several route guards then the router wouldn't know where to navigate to, by returnin a UrlTree this problem is resolved.你应该看到它是这样的,如果你在几个路由守卫中调用this.router.navigate那么路由器将不知道导航到哪里,通过返回一个 UrlTree 这个问题就解决了。 See also a related question/answer here另请参阅此处的相关问题/答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM