簡體   English   中英

組件在保護后不呈現,角度為 9

[英]Components doesn't render after guard, angular 9

我正在嘗試使用AuthGuard中間件保護經過身份驗證的路由。 當我將此中間件實現到路由中時。 我激活守衛后這些路線不起作用。

應用路由模塊

const routes: Routes = [
  {
    path: 'posts',
    canLoad: [AuthGuardMiddleware],
    loadChildren: () => import('./modules/posts/posts.module').then(m => m.PostsModule)
  },
  {
    path: 'users',
    canLoad: [AuthGuardMiddleware],
    loadChildren: () => import('./modules/users/users.module').then(m => m.UsersModule)
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    preloadingStrategy: PreloadAllModules
  })],
  exports: [RouterModule]
})

和 AuthGuard 中間件

@Injectable({
  providedIn: 'root'
})
export class AuthGuardMiddleware implements CanActivate, CanLoad {
  constructor(private authService: AuthService, private router: Router) {
  }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> {
    return this.authService.user.pipe(map(user => {
      if (user) {
        return true;
      }
      return this.router.createUrlTree(['/login']);
    }));
  }

  canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean {
    return this.authService.user.pipe(map(user => {
      if (user) {
        return true;
      }
      this.router.navigate(['/']);
      return false;
    }));
  }
}

我該如何解決? 注意:AuthService::user 類型是 BehaviorSubject 初始化為 null

更新

我意識到當我清理我的應用程序組件並刪除條件路由器插座時,一切都開始正常工作。 我仍然不知道究竟是什么導致了這個錯誤。

應用組件

export class AppComponent implements OnInit {
  currentUrl: string;
  isAuthRoute = false;

  constructor(private router: Router) {
  }

  ngOnInit() {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        this.currentUrl = event.url;
        this.isAuthRoute = ['/login', '/register']
          .indexOf(this.currentUrl) !== -1;
      }
    });
  }
}

應用組件視圖

<div *ngIf="!isAuthRoute">
  <div class="row page-wrapper">
    <div class="col-md-3 col-md-pull-9">
      <app-sidebar></app-sidebar>
    </div>
    <div class="col-md-9 col-md-push-3 content-area">
      <router-outlet></router-outlet>
    </div>
  </div>
</div>

<div style="height: 80vh" class="d-flex justify-content-center align-items-center" *ngIf="isAuthRoute">
  <router-outlet ></router-outlet>
</div>

您的AuthService.user返回一個 Observable 流並且它永遠不會完成。 據我所知, canLoadcanActivate需要一個完整的Observable 您可以使用take(1)運算符來實現:

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> {
    return this.authService.user.pipe(
       map(user => {
        if (user) {
          return true;
        }
        return this.router.createUrlTree(['/login']);
      }),
      take(1)
    );
  }

  canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean {
    return this.authService.user.pipe(
      map(user => {
        if (user) {
          return true;
        }
        this.router.navigate(['/']);
        return false;
      }),
      take(1)
    );
  }

我想這可能發生的另一個原因是因為您正在使用PreloadAllModules策略。 這將立即加載所有模塊,但我想這是在用戶尚未登錄時完成的,因此守衛將返回 false 並且模塊不會加載,也不會重試。

因此,如果您使用PreloadAllModules ,您需要重新考慮是否要以這種方式使用canLoad保護。 也許canActivate守衛就足夠了。

您還可以實現自定義預加載策略,以某種方式等待用戶登錄加載它


有了關於條件路由器插座的附加信息,這是有道理的,因為首先組件將放置在一個router-outlet ,但是在路由完成后,另一個router-outlet變得可見,但沒有放置任何東西在那里:)。 你可以通過使用ngTemplateOutlet指令來更新你的模板來規避這個:

<ng-template #outlet>
  <router-outlet ></router-outlet>
</ng-template>

<div *ngIf="!isAuthRoute">
  <div class="row page-wrapper">
    <div class="col-md-3 col-md-pull-9">
      <app-sidebar></app-sidebar>
    </div>
    <div class="col-md-9 col-md-push-3 content-area">
      <ng-component [ngTemplateOutlet]="outlet"></ng-component>
    </div>
  </div>
</div>

<div style="height: 80vh" class="d-flex justify-content-center align-items-center" *ngIf="isAuthRoute">
  <ng-component [ngTemplateOutlet]="outlet"></ng-component>
</div>

通過這種方式,您可以確保AppComponent中只放置一個router-outlet ,這是應該完成的方式

我看不到您在 AppRoutingModule 中使用 AuthGuard 的位置。

嘗試將其應用於任何路線,例如:

{
    path: 'posts',
    canLoad: [AuthGuard],
    loadChildren: () => import('./modules/posts/posts.module').then(m => m.PostsModule),
},

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM