Angular 9 - onSameUrlNavigation='reload' 不触发路由器事件

Aug*_*mer 5 angular-routing angular angular9

我的 Angular 9 应用程序有一个 CustomErrorHandler 和一个 ErrorPageComponent。当整个应用程序抛出任何异常时,CustomErrorHandler 将告诉路由器导航到 ErrorPageComponent。但是,ErrorPageComponent 内部有一个按钮可能会抛出自己的异常,在这种情况下,我希望 CustomErrorHandler 仍然告诉路由器导航到 ErrorPageComponent,就像正常情况一样。然而,当ErrorPageComponent以这种方式路由到自身时,它需要再次调用其初始化方法。

通常,如果您希望组件在路由到自身后调用初始化方法,只需订阅路由事件即可。然后,只要你正确设置了 onSameUrlNavigation 来重新加载,当组件导航到自身时,路由器就会触发一个路由事件,并调用你的组件订阅它的回调方法。

但是,当我的 CustomErrorHandler 告诉路由器导航到 ErrorPageComponent 时,不会触发任何路由事件。

如果您查看代码,这会更有意义:

这是我在 app-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 { }
Run Code Online (Sandbox Code Playgroud)

这是 CustomErrorHandler ,它将重定向到 ErrorPageComponent:

@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']));
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,这是 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
  }
}
Run Code Online (Sandbox Code Playgroud)

正如我在代码注释中提到的,我已经确认 CustomErrorHandler 正在正确处理错误,并且正在调用路由器导航方法。但是,传递给路由器导航事件的订阅回调方法永远不会被调用。我究竟做错了什么?如何订阅ErrorPageComponent中的路由事件?

Ale*_*xis 8

您是否尝试过首先重定向到虚拟位置,然后重定向到实际组件,

this.router.navigateByUrl('/', {skipLocationChange: true}).then(()=>
     this.router.navigate(['/error'])
);
Run Code Online (Sandbox Code Playgroud)

我建议您将第一个位置设置为 ngOnInit 和 ngOnDestroy 不执行大量操作的位置,因为这将在路由到新位置之前等待 init 和 destroy。

这样做你不需要使用onSameUrlNavigation,我认为这更好,因为你不需要使用订阅,所以销毁它,你不必设置onSameUrlNavigation,你可以在需要时使用简单的函数简单地重新加载。

但如果您想使用订阅,请将其移至构造函数而不是函数中ngOnInit