在配置根路由时,可以对路由进行一系列的配置,具体的配置项写在RouterModule.forRoot(routes: Route[], config?: ExtraOptions)的 config中
首先我们看看ExtraOptions接口是什么
interface ExtraOptions {
enableTracing?: boolean
useHash?: boolean
initialNavigation?: InitialNavigation
errorHandler?: ErrorHandler
preloadingStrategy?: any
onSameUrlNavigation?: 'reload' | 'ignore'
scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'
anchorScrolling?: 'disabled' | 'enabled'
scrollOffset?: [number, number] | (() => [number, number])
paramsInheritanceStrategy?: 'emptyOnly' | 'always'
malformedUriErrorHandler?: (error: URIError, urlSerializer: UrlSerializer, url: string) => UrlTree
urlUpdateStrategy?: 'deferred' | 'eager'
relativeLinkResolution?: 'legacy' | 'corrected'
}
-
enableTracing是一个boolean,将其配置为ture时可以将内部导航事件记录到控制台,下面是配置后打印的结果
const routes: Routes = [ { path: 'first-component', component: FirstComponent }, { path: 'second-component', component: SecondComponent }, ]; @NgModule({ imports: [RouterModule.forRoot(routes,{ enableTracing: true })], exports: [RouterModule] }) export class AppRoutingModule { }<!-- 组件省略 --> <div> <a nz-button routerLink="/first-component" routerLinkActive="active">组件一</a> <a nz-button routerLink="/second-component" routerLinkActive="active">组件二</a> </div>上面的图可以清晰的看到整个导航过程中,事件触发的先后顺序
-
useHash:boolean 修改位置策略,用 URL 片段(
#)代替historyAPI, 设定使用哈希模式还是使用history模式,默认为false,使用history -
initialNavigation 设置导航在AppComponent创建前开始还是创建后开始, 默认是enabledNonBlocking:在创建根组件之后开始初始导航,引导程序不会被阻止。 enabledBlocking:初始导航在创建根组件之前开始,引导程序将被阻止,该值是让
服务器渲染正常工作所必需的。 -
errorHandler 导航失败的自定义错误处理器。当路由发生错误时,可以捕获错误
- 当不捕获错误时,如果匹配路由失败时会如以下报错
2. 自定义错误处理函数
// 自定义ErrorHandle class MyErrorHandler implements ErrorHandler { handleError(error: any) { console.warn('当路由发生错误时,可以自定义错误处理函数') } } // App.module.ts @NgModule({ ... providers: [ { provide: ErrorHandler, useClass: MyErrorHandler } // 声明token,这样就可以自己实现路由错误处理函数了 ], ... }) -
preloadingStrategy 配置预加载策略,在程序空闲时尽快预加载所有模块。
-
当你需要采用这种预加载策略时,你只需要在RouterModule.forRoot中配置
preloadingStrategy@NgModule({ imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })] }) -
你也可以自定义预加载模式,比如程序加载完毕3秒后加载预加载模块
// app-routing.module.ts const routes: Routes = [ { path: 'first-component', component: FirstComponent }, { path: 'second-component', component: SecondComponent }, { path: 'load', loadChildren: () => import('./load/load.module').then(m => m.LoadModule), data: { preload: true // 用data中的preload作为标示判断是否采用PreloadAllModules模式 }, }, { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule), data: { preload: true, // 用data中的preload作为标示判断是否采用PreloadAllModules模式 delay: 3000 // 3000毫秒后加载,如果当前访问的路由是home模块下的page则立即加载 }, }, ]; // app.module.ts class ServicePreloadingStrategy implements PreloadingStrategy { preload(route: Route, load: () => import("rxjs").Observable<any>): Observable<any> { return route.data && route.data.preload ? timer(route.data.delay || 0).pipe( mergeMap(() => load()) ) : of(null); } } // 这样home模块就会在程序运行完毕后3秒再加载对应模块 @NgModule({ ... providers: [ { provide: PreloadingStrategy, useClass: ServicePreloadingStrategy }, ], ... })
-
-
onSameUrlNavigation 导航到当前 URL 的请求时该如何处理,默认的情况会忽略本次导航,但是如果你是进行刷新操作,则不会忽略
-
两种模式,默认是
ignore当你配置为reload时导航将不会忽略@NgModule({ ... imports: [RouterModule.forRoot(routes, { onSameUrlNavigation: 'reload' // 采用reload模式,默认是ignore模式 })], ... }) export class HomePageComponent implements OnInit { constructor( private router: Router, private route: ActivatedRoute ) { this.route.url.subscribe(console.log) // 采用reload模式后,调用goSelf方法,url会再次被订阅到值 // 如果你设置了enableTracing: true,则可以再次看到URL跳转时触发函数的整个周期。 } goSelf(){ this.router.navigateByUrl('/home/home-page') } }
-
-
scrollPositionRestoration配置是否需要在导航回来的时候恢复滚动位置-
默认是
disabled什么也不做,top每次导航回来都把滚动位置设置为 x=0, y=0。enabled当向后导航时,滚动到以前的滚动位置 -
如果你想导航回来时,滚动到上次的位置
@NgModule({ ... imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' // 恢复上次滚动的位置 })], ... }) -
你可以自定义恢复滚动策略
export class AppComponent { constructor( private router: Router, viewportScroller: ViewportScroller ){ this.router.events.pipe( filter(e=> e instanceof Scroll) ).subscribe(route=>{ route = route as Scroll; if (route.position){ viewportScroller.scrollToPosition(route.position) // route会记住上次导航离开的position,当再次导航回来时,可以将滚动条设置到记忆的位置 }else if(route.anchor){ viewportScroller.scrollToAnchor(route.anchor) }else{ viewportScroller.scrollToPosition([0,0]) } }) } }
-
-
anchorScrolling 如果 URL 有一个片段,就滚动到锚点元素
-
导航回来,滚动到指定的元素
-
默认为
disabled禁止滚动到锚点,如果你设置了enabled则可以滚动到指定元素@NgModule({ imports: [RouterModule.forRoot(routes, { anchorScrolling: 'enabled', })], ... }) // home-page.component.ts export class HomePageComponent implements OnInit { constructor( private router: Router ) { } goSelf(){ this.router.navigate(['home','home-page'],{ fragment: 'top' }) } }<!-- home-page.component.html -> <div class="home-page"> <button nz-button (click)="goSelf()">跳转到自己</button><br/> <a [routerLink]="['/home/home-page']" fragment="top">跳转到自己</a> <h1 id="top">目标元素</h1> </div>
-
-
scrollOffset 配置当滚动到一个元素时,路由器使用的滚动偏移
-
一般会搭配上面的
anchorScrolling使用,在滚动到指定元素的基础上再进行偏移imports: [RouterModule.forRoot(routes, { anchorScrolling: 'enabled', scrollOffset: [0,100] // 向下偏移100px })],
-
-
paramsInheritanceStrategy 定义路由器如何将参数、数据和已解析的数据从父路由合并到子路由
-
默认情况下
emptyOnly继承无路径或无组件路由的父参数,例如const routes: Routes = [ { path: 'second-component/:pid', component: SecondComponent, children: [ { path: '', component: SecondIndexComponent}, // 这种无路径的路由会合并到子路由 { path: 'child', component: SecondChildComponent}, // 有路径的就无法合并子路由 ] }, ]; -
使用
always选项后会始终启用父参数的无条件继承// 当我们在SecondChildComponent中想获取pid的参数是就需要配置always @NgModule({ imports: [RouterModule.forRoot(routes, { paramsInheritanceStrategy: 'always', })], exports: [RouterModule] }) // second-child.component.ts export class SecondChildComponent implements OnInit { constructor( private route: ActivatedRoute ) { } ngOnInit(): void { console.log('params', this.route.snapshot.params); // 配置了'always'才能拿到pid } }
-