Angular特性模块下添加全局404路由的最佳实践
解决Angular特性模块路由后添加404通配符路由的问题
你的问题核心有两个关键错误点,我们一步步来修复,同时遵循Angular路由的最佳实践:
步骤1:修复特性模块的路由注册方式
首先,你所有特性模块(比如OrderRoutingModule)里用了RouterModule.forRoot(routes),这是绝对错误的。forRoot()是用来初始化根路由器的方法,只能在根路由模块(AppRoutingModule)中调用一次,特性模块必须用forChild()来注册子路由,否则会导致路由器配置冲突,打乱整个路由树结构。
修改后的OrderRoutingModule代码:
const routes: Routes = [ { path: '', children: [ { path: 'orderSearch', component: OrderSearchComponent, data: { title : 'Order Search'}, canActivate: [AuthorityChecker], resolve: {translation: OrderBundleResolve }}, { path: 'orderEdit/:orderID', component: OrderEditComponent, data: { title : 'Order Edit'}, canActivate: [AuthorityChecker], canDeactivate: [ConfirmLooseChanges], resolve: {translation: OrderBundleResolve }}, { path: 'orderAdd', component: OrderAddComponent, data: { title : 'Order Add'}, canActivate: [AuthorityChecker], canDeactivate: [ConfirmLooseChanges], resolve: {translation: OrderBundleResolve }}, ], resolve: {translation: BaseTranslationResolve } } ]; @NgModule({ imports: [RouterModule.forChild(routes)], // 把forRoot替换为forChild exports: [RouterModule] }) export class OrderRoutingModule { }
所有其他特性模块的路由模块都要做同样的修改。
步骤2:正确放置通配符路由
你之前把{ path: '**', component: PageNotFoundComponent }放在了空路径的children数组末尾,这会导致特性模块的路由被追加到通配符路由之后——因为Angular会按照模块导入顺序合并路由,特性模块是在AppRoutingModule之后导入的,所以它们的路由会排在通配符路由后面,而通配符会优先匹配所有路径,导致所有有效路由都失效。
正确的做法是把通配符路由放在根路由数组的最后,作为独立的路由项,确保它在所有其他路由(包括App自身路由和特性模块路由)之后被匹配。
修改后的AppRoutingModule代码:
const routes: Routes = [ { path: '', children: [ { path: '', redirectTo: '/pleaseSelect', pathMatch: 'full' }, { path: 'restricted', component: AuthorityRestrictedComponent, data: { title : 'Restricted'}, canActivate: [AuthorityChecker] }, { path: 'pleaseSelect', component: PleaseSelectComponent, data: { title : 'Please Select'}, canActivate: [AuthorityChecker] }, { path: 'notAuthorized', component: NotAuthorizedComponent, data: { title : 'Not Authorized'}, canActivate: [AuthorityChecker] } ], resolve: {translation: BaseTranslationResolve } }, // 通配符路由放在根路由数组的最后,确保所有有效路由都先被匹配 { path: '**', component: PageNotFoundComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes, { enableTracing: false } )], exports: [RouterModule] }) export class AppRoutingModule { }
为什么这样能解决问题?
forChild()的作用:特性模块用forChild()注册路由时,Angular会把这些路由合并到根路由树的对应节点下,不会重置整个路由器配置。- 路由匹配顺序:Angular路由是按数组顺序从上到下匹配的,通配符路由放在最后,只有当所有前面的有效路由都匹配失败时,才会触发404页面。
额外最佳实践
- 只在
AppRoutingModule中使用forRoot(),所有特性模块统一用forChild()。 - 如果使用懒加载模块,同样要保证懒加载路由的定义在通配符路由之前(Angular会自动处理懒加载路由的优先级,只要通配符在根路由最后)。
- 可以开启
enableTracing: true临时调试路由匹配过程,方便排查问题。
内容的提问来源于stack exchange,提问作者Scott
相关产品推荐
相关产品推荐

