angular+ 路由学习 (九)异步路由都预加载
- 异步路由的预加载示例: 为了尽可能减小初始加载体积和最快的加载速度,让 主模块和A模块 先加载;如何懒加载其他模块,但是B 模块可能是 用户在打开应用后,几分钟或几秒钟就会访问的模块;(比如打开微信后,是不是进入主页面;然后是不是要打开朋友圈瞅瞅;而B模块就相当于朋友圈功能;)所以,这个时候在用户打开B模块前;该模块就已经预加载完毕可供访问;
- 预加载原理:
- 每次成功导航后,路由器会在自己的配置中查找尚未加载并且可以预加载的模块
- 预加载策略:
- 默认 都不预加载,懒加载的模块仍会按需加载
- 预加载所有懒加载模块
- 自定义预加载
- 用户场景:将CrisisCenterModule 改为默认懒加载,并使用全部预加载策略来加载所有懒加载模块
- 对crisis-center 模块进行懒加载处理
// crisis-center-routing.ts 该路径为空路径 const crisisCenterRoutes: Routes = [ { path: '', component: CrisisCenterComponent, children: [ { path: '', component: CrisisListComponent, children: [ // tslint:disable-next-line: max-line-length { path: ':id', component: CrisisDetailComponent, canDeactivate: [CanDeactivateGuard], resolve: { crisis: CrisisDetailResolverService }}, { path: '', component: CrisisCenterHomeComponent} ]} ] } ]; // AppRoutingModule 增加该模块路由,并设置loadChildren const appRoutes: Routes = [ { path: 'compose', component: ComposeMessageComponent, outlet: 'popup' }, { path: 'admin', loadChildren: () => import('./admin/admin.module').then(mod => mod.AdminModule), canLoad: [AuthGuard] }, { path: 'crisis-center', loadChildren: () => import('./crisis-center/crisis-center.module').then(mod => mod.CrisisCenterModule), data: { preload: true } // 自定义预加载 }, { path: '', redirectTo: '/superheroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; // AppModule 中 移除该模块 import { HeroesModule } from './heroes/heroes.module'; // import { CrisisCenterModule } from './crisis-center/crisis-center.module'; // import { AdminModule} from './admin/admin.module'; import { AuthModule} from './auth/auth.module'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; // 导入动画模块 import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { ComposeMessageComponent } from './compose-message/compose-message.component'; @NgModule({ declarations: [ AppComponent, PageNotFoundComponent, ComposeMessageComponent ], imports: [ BrowserModule, FormsModule, HeroesModule, // CrisisCenterModule, // AdminModule, AuthModule, AppRoutingModule, BrowserAnimationsModule ],
- 为所有懒加载模块启动预加载功能,在AppRoutingModule 中导入PreloadAllModules
import { NgModule } from '@angular/core'; import { RouterModule, Routes, PreloadAllModules } from '@angular/router'; import { ComposeMessageComponent } from './compose-message/compose-message.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { AuthGuard } from './auth/auth.guard'; const appRoutes: Routes = [ { path: 'compose', component: ComposeMessageComponent, outlet: 'popup' }, { path: 'admin', loadChildren: () => import('./admin/admin.module').then(mod => mod.AdminModule), canLoad: [AuthGuard] //CanLoad 会阻塞预加载,该优先级高于预加载策略 }, { path: 'crisis-center', loadChildren: () => import('./crisis-center/crisis-center.module').then(mod => mod.CrisisCenterModule), data: { preload: true } }, { path: '', redirectTo: '/superheroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; @NgModule({ imports: [ RouterModule.forRoot( appRoutes, { enableTracing: false, preloadingStrategy: PreloadAllModules, //让所有(带loadChildren属性的路由)懒加载模块立即预加载 } ) ], exports: [ RouterModule ] }) export class AppRoutingModule { }
- 关于自定义预加载;这里自定义策略为:只预加载data.preload 为 true 的路由;
- 生成自定义服务
ng generate service selective-preloading-strategy import { Injectable } from '@angular/core'; import { PreloadingStrategy, Route } from '@angular/router'; import { Observable, of } from 'rxjs'; @Injectable({ providedIn: 'root', }) export class SelectivePreloadingStrategyService implements PreloadingStrategy { preloadedModules: string[] = []; // 参数 route -- 要加载的路由 load() -- 加载器函数,异步加载带路由的模块 // 如果该路由应该预加载,就会跳用load()函数返回Observable对象,否则返回null; preload(route: Route, load: () => Observable<any>): Observable<any> { if (route.data && route.data['preload']) { this.preloadedModules.push(route.path); //会将所选路由记录在数组中; console.log('Preloaded: ' + route.path); return load(); } else { return of(null); } } }
- 自定义预加载处理
// AppRoutingModule import { NgModule } from '@angular/core'; import { RouterModule, Routes, PreloadAllModules } from '@angular/router'; import { ComposeMessageComponent } from './compose-message/compose-message.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { AuthGuard } from './auth/auth.guard'; import { SelectivePreloadingStrategyService } from './selective-preloading-strategy.service'; const appRoutes: Routes = [ { path: 'compose', component: ComposeMessageComponent, outlet: 'popup' }, { path: 'admin', loadChildren: () => import('./admin/admin.module').then(mod => mod.AdminModule), canLoad: [AuthGuard] }, { path: 'crisis-center', loadChildren: () => import('./crisis-center/crisis-center.module').then(mod => mod.CrisisCenterModule), data: { preload: true } }, { path: '', redirectTo: '/superheroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; @NgModule({ imports: [ RouterModule.forRoot( appRoutes, { enableTracing: false, preloadingStrategy: SelectivePreloadingStrategyService, } ) ], exports: [ RouterModule ] }) export class AppRoutingModule { }
- 编辑adminDashboardComponent 来显示预加载路由日志, 当加载完初始路由后,crisisCenterModule被预加载,通过该模块可以在控制台看到日志
// html <p>Dashboard</p> <p>Session ID: {{ sessionId | async }}</p> <a id="anchor"></a> <p>Token: {{ token | async }}</p> Preloaded Modules <ul> <li *ngFor="let module of modules">{{ module }}</li> </ul> // ts import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { SelectivePreloadingStrategyService } from '../../selective-preloading-strategy.service'; @Component({ selector: 'app-admin-dashboard', templateUrl: './admin-dashboard.component.html', styleUrls: ['./admin-dashboard.component.css'] }) export class AdminDashboardComponent implements OnInit { sessionId: Observable<string>; token: Observable<string>; modules: string[]; constructor( private route: ActivatedRoute, preloadStrategy: SelectivePreloadingStrategyService ) { this.modules = preloadStrategy.preloadedModules; } ngOnInit() { this.sessionId = this.route .queryParamMap .pipe(map(params => params.get('session_id') || 'None')); this.token = this.route .fragment .pipe(map(fragment => fragment || 'None')); } }
想买的东西很贵,想去的地方很远,喜欢的女孩很完美