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

Я столкнулся со следующей проблемой: раздел personal, защищенный с помощью службы 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, войдя в систему с именем пользователя/паролем - [email protected]/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);
  });
}

person ama    schedule 28.08.2017    source источник
comment
Можете ли вы попробовать добавить непустой путь для BookmarksComponent   -  person Robin Dijkhof    schedule 05.09.2017
comment
Я пробовал это, но получил такое же поведение, почему это должно помочь?   -  person ama    schedule 06.09.2017
comment
@ama Вы решили эту проблему, если да, можете ли вы опубликовать свой ответ? Я также сталкиваюсь с той же проблемой: модуль ленивой загрузки, четырехкратный вызов дочернего маршрута, я также не использую маскировку ключей или защиту. Просто ленивая загрузка модуля и дочерних компонентов.   -  person Cegone    schedule 03.07.2020
comment
и это произошло только тогда, когда я пытаюсь перейти к модулю по URL-адресу, например http:/localhost:4200/#/ps/container. Это не происходит, когда я перехожу с одного маршрута на другой маршрут   -  person Cegone    schedule 03.07.2020


Ответы (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]
})
person Rahul Singh    schedule 06.09.2017
comment
PersonalBookmarksComponent содержит только маршрутизатор-выход для отображения личных дочерних представлений... Этот подход также используется в официальном руководстве по маршрутизатору - angular.io/generated/live-examples/router/eplnkr.html Тем не менее, даже если я изменю его на непустой (оставлю дочерний элемент пустым) или изменю дочерний компонент на непустой и оставить родительский путь пустым, то же поведение остается... Я начинаю думать, что это может иметь какое-то отношение к keycloak js adatper - person ama; 07.09.2017
comment
@ Адриан, вы можете создать небольшую демонстрацию, воспроизводящую эту проблему в stackblitz, так как это должно было сработать - person Rahul Singh; 07.09.2017

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

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

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

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

person Chirag Khanna    schedule 09.09.2017
comment
Эй, Чираг, это тоже не помогло - смотрите обновление в моем вопросе... - person ama; 10.09.2017