Angular 9 - onSameUrlNavigation='reload' 未触发路由器事件
Angular 9 - onSameUrlNavigation='reload' not triggering router event
我的 Angular 9 应用程序有一个 CustomErrorHandler 和一个 ErrorPageComponent。当整个应用程序抛出任何异常时,CustomErrorHandler 将告诉路由器导航到 ErrorPageComponent。但是,ErrorPageComponent 中有一个按钮 可以 抛出自己的异常,在这种情况下,我希望 CustomErrorHandler 仍然告诉路由器导航到 ErrorPageComponent,这是正常的。但是当ErrorPageComponent这样路由到自己时,需要二次调用它的初始化方法
通常情况下,如果你想让一个组件在路由到它自己之后调用一个初始化方法,你可以简单地订阅路由事件。然后,只要你正确设置了onSameUrlNavigation重新加载,当组件导航到自己时,路由器会触发一个路由事件,调用你的组件订阅它的回调方法。
但是,当我的 CustomErrorHandler 告诉路由器导航到 ErrorPageComponent 时,没有触发路由事件。
如果您查看代码,这将更有意义:
这是我在应用程序中的路由配置-routing.module.ts:
const routes: Routes = [
{ path: 'normal', component: NormalComponent},
{ path: '', redirectTo: '/normal', pathMatch: 'full'}
];
const volitileRoutes: Routes = [
{ path: 'error', component: ErrorPageComponent}
];
const fallbackRoute: Routes = [
{ path: '**', component: Error404PageComponent }
];
@NgModule({
imports: [
RouterModule.forRoot(routes),
RouterModule.forRoot(volitileRoutes, {onSameUrlNavigation: 'reload'}), // I've correctly set onSameUrlNavigation
RouterModule.forRoot(fallbackRoute)
],
exports: [RouterModule]
})
export class AppRoutingModule { }
这是将重定向到 ErrorPageComponent 的 CustomErrorHandler:
@Injectable({
providedIn: 'root'
})
export class CustomErrorHandler extends ErrorHandler {
constructor(private ngZone: NgZone, private router: Router){
super();
}
handleError(error: any){
// error handling code here
console.log('error caught'); // I've confirmed that my CustomErrorHandler is in fact handling errors.
/* This is not the normal way to do navigation. But for reasons I don't understand, this
is the only way to get navigation to work from within an ErrorHandler; you cannot simply
call router.navigate like normal from within an ErrorHandler. */
this.ngZone.run(() => this.router.navigate(['/error']));
}
}
最后,这里是 ErrorPageComponent:
@Component({
selector: 'app-error-page',
templateUrl: './error-page.component.html',
styleUrls: ['./error-page.component.css']
})
export class ErrorPageComponent implements OnInit, OnDestroy {
private navSubscription = new Subscription();
constructor(private router: Router) { }
ngOnInit(): void {
this.navSubscription = this.router.events.subscribe((e: any) => {
console.log('route event triggered'); // this line is never reached
if (e instanceof NavigationEnd) {
// do initialization code
}
});
}
ngOnDestroy(): void {
this.navSubscription?.unsubscribe(); // this prevents a memory leak
}
}
正如我在代码注释中提到的,我已经确认 CustomErrorHandler 正在正确处理错误,并且正在调用路由器导航方法。但是,永远不会调用传递给路由器导航事件的订阅回调方法。我究竟做错了什么?如何订阅 ErrorPageComponent 中的路由事件?
您是否尝试过先重定向到虚拟位置,然后再重定向到您的实际组件,
this.router.navigateByUrl('/', {skipLocationChange: true}).then(()=>
this.router.navigate(['/error'])
);
我建议您将第一个位置设置为 ngOnInit 和 ngOnDestroy 没有执行很多操作的位置,因为这将在路由到新位置之前等待初始化和销毁。
这样做你不需要使用onSameUrlNavigation
,我认为这样更好,因为你不需要使用订阅,所以销毁它,你不必设置onSameUrlNavigation
并且您可以在需要时使用简单的功能简单地重新加载。
但是,如果您想使用订阅,请将其移动到您的构造函数中,而不是在您的 ngOnInit
函数中。
我的 Angular 9 应用程序有一个 CustomErrorHandler 和一个 ErrorPageComponent。当整个应用程序抛出任何异常时,CustomErrorHandler 将告诉路由器导航到 ErrorPageComponent。但是,ErrorPageComponent 中有一个按钮 可以 抛出自己的异常,在这种情况下,我希望 CustomErrorHandler 仍然告诉路由器导航到 ErrorPageComponent,这是正常的。但是当ErrorPageComponent这样路由到自己时,需要二次调用它的初始化方法
通常情况下,如果你想让一个组件在路由到它自己之后调用一个初始化方法,你可以简单地订阅路由事件。然后,只要你正确设置了onSameUrlNavigation重新加载,当组件导航到自己时,路由器会触发一个路由事件,调用你的组件订阅它的回调方法。
但是,当我的 CustomErrorHandler 告诉路由器导航到 ErrorPageComponent 时,没有触发路由事件。
如果您查看代码,这将更有意义:
这是我在应用程序中的路由配置-routing.module.ts:
const routes: Routes = [
{ path: 'normal', component: NormalComponent},
{ path: '', redirectTo: '/normal', pathMatch: 'full'}
];
const volitileRoutes: Routes = [
{ path: 'error', component: ErrorPageComponent}
];
const fallbackRoute: Routes = [
{ path: '**', component: Error404PageComponent }
];
@NgModule({
imports: [
RouterModule.forRoot(routes),
RouterModule.forRoot(volitileRoutes, {onSameUrlNavigation: 'reload'}), // I've correctly set onSameUrlNavigation
RouterModule.forRoot(fallbackRoute)
],
exports: [RouterModule]
})
export class AppRoutingModule { }
这是将重定向到 ErrorPageComponent 的 CustomErrorHandler:
@Injectable({
providedIn: 'root'
})
export class CustomErrorHandler extends ErrorHandler {
constructor(private ngZone: NgZone, private router: Router){
super();
}
handleError(error: any){
// error handling code here
console.log('error caught'); // I've confirmed that my CustomErrorHandler is in fact handling errors.
/* This is not the normal way to do navigation. But for reasons I don't understand, this
is the only way to get navigation to work from within an ErrorHandler; you cannot simply
call router.navigate like normal from within an ErrorHandler. */
this.ngZone.run(() => this.router.navigate(['/error']));
}
}
最后,这里是 ErrorPageComponent:
@Component({
selector: 'app-error-page',
templateUrl: './error-page.component.html',
styleUrls: ['./error-page.component.css']
})
export class ErrorPageComponent implements OnInit, OnDestroy {
private navSubscription = new Subscription();
constructor(private router: Router) { }
ngOnInit(): void {
this.navSubscription = this.router.events.subscribe((e: any) => {
console.log('route event triggered'); // this line is never reached
if (e instanceof NavigationEnd) {
// do initialization code
}
});
}
ngOnDestroy(): void {
this.navSubscription?.unsubscribe(); // this prevents a memory leak
}
}
正如我在代码注释中提到的,我已经确认 CustomErrorHandler 正在正确处理错误,并且正在调用路由器导航方法。但是,永远不会调用传递给路由器导航事件的订阅回调方法。我究竟做错了什么?如何订阅 ErrorPageComponent 中的路由事件?
您是否尝试过先重定向到虚拟位置,然后再重定向到您的实际组件,
this.router.navigateByUrl('/', {skipLocationChange: true}).then(()=>
this.router.navigate(['/error'])
);
我建议您将第一个位置设置为 ngOnInit 和 ngOnDestroy 没有执行很多操作的位置,因为这将在路由到新位置之前等待初始化和销毁。
这样做你不需要使用onSameUrlNavigation
,我认为这样更好,因为你不需要使用订阅,所以销毁它,你不必设置onSameUrlNavigation
并且您可以在需要时使用简单的功能简单地重新加载。
但是,如果您想使用订阅,请将其移动到您的构造函数中,而不是在您的 ngOnInit
函数中。