Загруженный ленивый дочерний маршрут загружается дважды в Angular

Я столкнулся со следующей проблемой: личный раздел, защищенный службой AuthGuard, загружается дважды, когда я перехожу к нему или обновляю браузер. Во второй раз он удаляет параметры запроса URL, если я предоставлю любой. Вот конфигурация роутера моего приложения:

const routes: Routes = [
  {
    path: 'search',
    redirectTo: '',
    pathMatch: 'full'
  },
  {
    path: '',
    component: BookmarksComponent
  },
  {
    path: 'tagged/:tag',
    component: TagComponent
  },
  {
    path: 'about',
    component: AboutComponent
  },
  {
    path: 'personal',
    loadChildren: 'app/personal/personal-bookmarks.module#PersonalBookmarksModule'
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

и дочерняя конфигурация роутера

@NgModule({
  imports: [RouterModule.forChild([
    {
      path: '',
      component: PersonalBookmarksComponent,
      canActivate: [AuthGuard],
      children: [
        {
          path: '',
          component: PersonalBookmarksListComponent
        },
        {
          path: 'new',
          component: NewPersonalBookmarkFormComponent
        },
        {
          path: 'bookmarks/:id',
          component: PersonalBookmarkDetailComponent
        }
      ]
    }

  ])],
  exports: [RouterModule]
})
export class PersonalBookmarksRoutingModule {}

Служба AuthGuard (при этом, если она только возвращает true, то же самое поведение):

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private keycloakService: KeycloakService) {}

  canActivate() {
    console.log('AuthGuard#canActivate called');

    if (this.keycloakService.isLoggedIn()) {
      return true;
    } else {
      this.keycloakService.login();
    }
  }
}

И шаблон Navbar:

<nav class="navbar navbar-light bg-faded" id="navbar">
  <a class="navbar-brand" [routerLink]="['']" routerLinkActive="active">
    <img src="assets/logo.png" width="35" height="35" class="d-inline-block align-top" alt="">
    Public Bookmarks
  </a>
  <ul class="nav navbar-nav">
    <li class="nav-item">
      <a class="nav-link" [routerLink]="['personal']" routerLinkActive="active">Personal list</a>
    </li>
    <li class="nav-item">
      <a class="nav-link" [routerLink]="['about']" routerLinkActive="active">About</a>
    </li>
    <li class="nav-item">
      <a class="nav-link" href="http://www.codingpedia.org/tags/#codingmarks" target="_blank">Blog</a>
    </li>
    <li *ngIf="isLoggedIn else notLoggedIn" class="nav-item">
      <a class="nav-link" (click)="logout()">Logout <i class="fa fa-lock"></i></a>
    </li>
    <ng-template #notLoggedIn>
      <li *ngIf="!keycloakService.isLoggedIn()" class="nav-item">
        <a class="nav-link" (click)="login()">Login <i class="fa fa-unlock"></i></a>
      </li>
    </ng-template>
  </ul>
</nav>

Проект доступен на Github, а неисправное поведение можно проверить по адресу https://www.codingmarks.org/personal, выполнив вход с именем пользователя /pwd - test@codingmarks.org/Test_user1$.

ОБНОВЛЕНИЕ Даже если я удаляю PersonalBookmarksComponent и перемещаю AuthGuard в модуль PersonalBookmarks, неправильное поведение все еще сохраняется... Маршруты для PersonalBookmarksModule выглядят примерно так:

const personalBookmarksRoutes: Routes = [
    {
      path: 'search',
      redirectTo: '',
      pathMatch: 'full'
    },
    {
      path: '',
      component: PersonalBookmarksListComponent,
      canActivate: [AuthGuard],
    },
    {
      path: 'new',
      component: NewPersonalBookmarkFormComponent
    },
    {
      path: 'bookmarks/:id',
      component: PersonalBookmarkDetailComponent
    }

];

ОБНОВЛЕНИЕ 2: Удаление параметров запроса было связано с принудительным перенаправлением при входе в систему с Keycloak.

Ложь:

public login(): Promise<any> {
  let options: any;
  options = {redirectUri: environment.HOST + 'personal'};
  return new Promise<any>((resolve, reject) => {
    KeycloakService.auth.login(options)
      .success(resolve)
      .error(reject);
  });
}

Исправить:

public login(): Promise<any> {
  return new Promise<any>((resolve, reject) => {
    KeycloakService.auth.login()
      .success(resolve)
      .error(reject);
  });
}

2 ответа

Причина, по которой маршруты загружаются дважды, заключается в том, что вы указали путь маршрутизатора для загрузки двух компонентов, когда переходите к этому ' ' маршрут.

изменить конфигурацию маршрутизатора на

@NgModule({
  imports: [RouterModule.forChild([
    {
      path: '',
      //component: PersonalBookmarksComponent, //either remove this component line completely [best way is to remove this component deceleration]
      canActivate: [AuthGuard],
      children: [
        {
          path: '', // or specify a different route to this better use a redirect option on path 
          component: PersonalBookmarksListComponent
        },
        {
          path: 'new',
          component: NewPersonalBookmarkFormComponent
        },
        {
          path: 'bookmarks/:id',
          component: PersonalBookmarkDetailComponent
        }
      ]
    }

  ])],
  exports: [RouterModule]
})

U может выполнить следующие два шага:

  1. Переместите authGuard в персональный модуль маршрутизации, это также улучшит вашу производительность, так как модуль не будет загружен в случае, если пользователь не аутентифицирован.
  2. Удалите компонент "PersonalBookmarksComponent", содержащий пустую розетку маршрутизатора, вместо этого предоставьте маршрутизатор для остальных наших компонентов напрямую.

Я верю, что такой подход решит вашу проблему.

Guard вызывается дважды, один раз для вашего компонента и один раз для вашего дочернего компонента.

Другие вопросы по тегам