Загруженный ленивый дочерний маршрут загружается дважды в 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 может выполнить следующие два шага:
- Переместите authGuard в персональный модуль маршрутизации, это также улучшит вашу производительность, так как модуль не будет загружен в случае, если пользователь не аутентифицирован.
- Удалите компонент "PersonalBookmarksComponent", содержащий пустую розетку маршрутизатора, вместо этого предоставьте маршрутизатор для остальных наших компонентов напрямую.
Я верю, что такой подход решит вашу проблему.
Guard вызывается дважды, один раз для вашего компонента и один раз для вашего дочернего компонента.