angular+ 路由学习 (九)异步路由都预加载

  • 异步路由的预加载示例: 为了尽可能减小初始加载体积和最快的加载速度,让 主模块和A模块 先加载;如何懒加载其他模块,但是B 模块可能是 用户在打开应用后,几分钟或几秒钟就会访问的模块;(比如打开微信后,是不是进入主页面;然后是不是要打开朋友圈瞅瞅;而B模块就相当于朋友圈功能;)所以,这个时候在用户打开B模块前;该模块就已经预加载完毕可供访问;
  • 预加载原理:
    •   每次成功导航后,路由器会在自己的配置中查找尚未加载并且可以预加载的模块
  • 预加载策略:
    •   默认 都不预加载,懒加载的模块仍会按需加载
    • 预加载所有懒加载模块
    • 自定义预加载
  • 用户场景:将CrisisCenterModule 改为默认懒加载,并使用全部预加载策略来加载所有懒加载模块
  1. 对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
      ],

     

  2. 为所有懒加载模块启动预加载功能,在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 { }

     

  3. 关于自定义预加载;这里自定义策略为:只预加载data.preload 为 true  的路由;
  4. 生成自定义服务
    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);
        }
      }
    }

     

  5. 自定义预加载处理
    // 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 { }

     

  6. 编辑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'));
      }
    }

     

 

posted @ 2019-07-31 15:36  抹茶奶盖xh  阅读(1102)  评论(0编辑  收藏  举报