【问题标题】:Angular 6: Convert eager loading to lazy loadingAngular 6:将急切加载转换为延迟加载
【发布时间】:2019-03-28 11:18:35
【问题描述】:

我有一个使用急切加载的完整 Angular 应用程序。 我想将其转换为延迟加载,但是因为我对所有路线都有保护,并且所有路线都是通往受保护的主要路线的子路线,所以我不知道是否可以这样做并且仍然使它起作用就像急切加载一样。

这是我在 app-routing.module 中的路由数组:

// Routing array - set routes to each html page
const appRoutes: Routes = [
  { path: 'login/:id', canActivate: [AuthGuard], children: [] },
  { path: '', canActivateChild: [AuthGuard], children: [
    { path: '', redirectTo: '/courses', pathMatch: 'full' },
    { path: 'courses', component: CourseListComponent,  pathMatch: 'full'},
    { path: 'courses/:courseId', component: CourseDetailComponent, pathMatch: 'full' },
    { path: 'courses/:courseId/unit/:unitId', component: CoursePlayComponent,
      children: [
        { path: '', component: CourseListComponent },
        { path: 'lesson/:lessonId', component: CourseLessonComponent, data:{ type: 'lesson'} },
        { path: 'quiz/:quizId', component: CourseQuizComponent, data: {type: 'quiz'} }
      ]}
    ]},
  { path: 'welcome', component: LandingPageComponent, pathMatch: 'full' },
  { path: '**', component: PageNotFoundComponent, pathMatch: 'full' }];

我想知道是否可以通过延迟加载来实现这一点,如果可以的话,我想知道主要思想或为此我需要知道什么。

在我做的所有教程中,我从未遇到过这种事情。 非常感谢

【问题讨论】:

  • 需要看canLoad的守卫方法。然后例如,如果您打算将所有 courses 作为延迟加载模块移动。然后为courses 模块创建一个路由配置,并有一个单独的守卫来管理它的子路径
  • 我需要把canLoad放在哪里?在应用程序路由模块上?或在课程模块中?如果你能解释一下我会很感激,我对这个延迟加载有点新
  • 如果你知道我可以从哪里得到一个我可以学习的例子,我会很棒
  • 我尝试转换为延迟加载,但在构建时遇到了很多错误。我更新了问题并添加了错误和我所做的更改。

标签: angular routing lazy-loading eager-loading angular-router-guards


【解决方案1】:

谢谢大家的回答。我成功地将我的路由转换为延迟加载。这是代码:

app-routing.module

import { NgModule } from '@angular/core';
import { Routes, RouterModule, Router } from '@angular/router';
import { AuthGuard } from './auth.guard';

import { AppComponent } from './app.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { LandingPageComponent } from './landing-page/landing-page.component';
import { HeaderComponent } from './header/header.component';
import { CourseModule } from './courses/course.module';


const routes:Routes = [
  { path: 'welcome', component: LandingPageComponent, pathMatch: 'full' },
  { path: 'login/:id', canActivate: [AuthGuard],  children: [] },
  { path: '', canActivateChild: [AuthGuard], children: [
    { path: '', redirectTo: 'courses', pathMatch: 'full' },
    { path: 'courses',  loadChildren: () => CourseModule }
  ]},
  { path: '**', component: PageNotFoundComponent, pathMatch: 'full' }
]

@NgModule({
  imports: [RouterModule.forRoot(routes, { onSameUrlNavigation: 'reload', initialNavigation: 'enabled',
      paramsInheritanceStrategy: 'always' })],
  providers: [AuthGuard],
  exports: [RouterModule]
})


export class AppRoutingModule {  }

course-routing.module

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from "@angular/router";
import { AuthGuard } from '../auth.guard';

import { CourseListComponent } from './course-list/course-list.component';
import { CourseDetailComponent } from './course-detail/course-detail.component';
import { CoursePlayComponent } from './course-play/course-play.component';
import { CourseQuizComponent } from './course-play/course-quiz/course-quiz.component';
import { CourseLessonComponent } from './course-play/course-lesson/course-lesson.component';


const routes:Routes = [
  { path: '', component: CourseListComponent, canActivate: [AuthGuard] },
  { path: ':courseId', component: CourseDetailComponent, canActivate: [AuthGuard] },
  { path: ':courseId/unit/:unitId', component: CoursePlayComponent, canActivate: [AuthGuard], canActivateChild: [AuthGuard], children: [
    { path: 'lesson/:lessonId', component: CourseLessonComponent, data:{ type: 'lesson'} },
    { path: 'quiz/:quizId', component: CourseQuizComponent, data: {type: 'quiz'}}
  ]}
]

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class CourseRoutingModule { }

auth.guard

import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { Router, CanActivate, CanActivateChild, CanLoad, ActivatedRouteSnapshot, RouterStateSnapshot, NavigationExtras, Route } from '@angular/router';
import { AuthUserService } from './users/auth-user.service';
import { LocalStorage } from '@ngx-pwa/local-storage';

@Injectable()
export class AuthGuard implements CanActivate , CanActivateChild {

    constructor(private authUserService: AuthUserService, private router: Router) {   }

    canActivate(route: ActivatedRouteSnapshot, state:
       RouterStateSnapshot): boolean |
       Observable<boolean> | Promise<boolean> {
         let id, course_id;

         // save the id from route snapshot
         if (route.params) {
           id = +route.params.id;
           course_id = +route.params.courseId;
         }

         // if you try to logging with id
         if (id) {
           this.router.navigate(["/courses"]);
           return this.authUserService.login(id);
         }

         // if you're already logged in and navigate between pages
         if (this.authUserService.isLoggedIn()){
           if (course_id){
             // check if someone try to access a locked course
             if (this.authUserService.isCourseNotPartOfTheSubscription(course_id)){
               this.router.navigate(["/welcome"]);
               return false;
             }
             else
               return true;
           }
           else
             return true;
         }

         // if you are not logged and didn't try to log - redirect to landing page
         else {
           this.router.navigate(["/welcome"]);
           return false;
         }
        }

      canActivateChild(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): boolean |
      Observable<boolean> | Promise<boolean> {
         return this.canActivate(route, state);
       }

       canLoad(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): boolean |
       Observable<boolean> | Promise<boolean> {
         return this.canActivate(route, state);
       }
}

【讨论】:

    【解决方案2】:

    带有一般问题标题“将急切加载转换为延迟加载”。

    我通过 4 个步骤分享我将急切加载转换为延迟加载的方法。

    第一步:在组件文件夹中通过命令 ng g module ModuleName 创建模块

    import { NgModule } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { RouterModule, Routes } from '@angular/router';
    import { AnalysisStatusComponent } from './analysis-status.component';
    import { ShareComponentModule } from '../../share-component/share-component.module';
    const routes: Routes = [
      {
        path: '',
        component: AnalysisStatusComponent
      }
    ];
    
    @NgModule({
      declarations: [
        AnalysisStatusComponent
      ],
      imports: [
        RouterModule.forChild(routes),
        CommonModule,
        ShareComponentModule
      ]
    })
    export class AnalysisStatusModule { }
    

    第 2 步:为模块添加路由

    const routes: Routes = [
          {
            path: '',
            component: AnalysisStatusComponent
          }
        ];
    

    第 3 步: 注释掉应用模块中的组件

    @NgModule({
       declarations: [
          AppComponent,
          NavBarComponent,
          LoginComponent,
          //AnalysisStatusComponent,
          PairsPipe,
          MainComponent
       ],
    

    第 4 步: 更新应用路由中的路由

    const routes: Routes = [
      //{ path: 'dashboard/analysis-status', component: AnalysisStatusComponent },
      { path: 'dashboard/analysis-status', loadChildren: './dashboard/analysis-status/analysis-status.module#AnalysisStatusModule' },
    }
    

    【讨论】:

    • 我对第4步有点困惑。我应该在哪个文件中添加这一步?
    • 第4步你应该在路由模块文件中更新,每个模块都有单独的路由文件。
    【解决方案3】:

    我的一个应用中的示例代码:

    const routes: Routes = [
      {
        path: 'login',
        component: SignupLoginMainContainerComponent,
        canActivate: [AuthGuard],
      },
      {
        path: 'error',
        component: ErrorComponent
      },
      {
        // lazy loading payment module
        path: 'payment',
        loadChildren: './modules/payment/payment.module#PaymentModule'
      },
      {
        // lazy loading private module
        path: '',
        loadChildren: './modules/private/private.module#PrivateModule',
        canLoad: [AuthGuard]
      },
      {path: '**', redirectTo: '/login'},
    ];
    

    AuthGuard 实现:

    export class AuthGuard implements CanActivate, CanLoad {
    
    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot
      ): Observable<boolean> | Promise<boolean> | boolean {
        return (some condition) ? true : false
      }
    
    canLoad(route: Route): boolean {
       return (some condition based on route etc) ? true : false
     }
    
    }
    

    私有模块拥有路由文件,进一步加载更多子模块:

    const routes: Routes = [
      {
        path: '',
        component: PrivateComponent,
        canActivateChild: [AuthGuard],
        children: [
          {
            path: 'childOne',
            loadChildren: '../child-one/child-one.module#ChildOneModule',
            canLoad: [AuthGuard],
          },
          {
            path: 'childTwo',
            loadChildren: '../child-two/child-two.module#ChildTwoModule',
            canLoad: [AuthGuard],
          },
          {
            path: '',
            redirectTo: '/dashboard',
            pathMatch: 'full',
          },
        ],
      },
    ];
    

    可以在以下位置找到另一个示例:https://github.com/ashishgkwd/bot/tree/24-lazy-loading-modulesAdminModule 在这个中被延迟加载。

    【讨论】:

    • 我尝试转换为延迟加载,但在构建时遇到了很多错误。我更新了问题并添加了错误和我所做的更改。
    • 错误不是直接指向问题,没有更多代码很难推断。但是,我看到在您的 app-routing.module.ts 中,{ path: 'login/:id', canActivate: [AuthGuard], children: [] }, 的映射没有任何组件或子级。
    【解决方案4】:
            For lazy loading you should use:
       import {ComponentName} from 'component path';     
            const routes: Routes = [
    
          //for module 
    
                {
                    path: 'path_Name',
                    loadChildren: './modules/abc/abc.module#AbcModule'
                },
    
           //for component
                {
                  path: 'browser',
                component: ComponentName
             },
        ];
    

    【讨论】:

    • 我尝试转换为延迟加载,但在构建时遇到了很多错误。我更新了问题并添加了错误和我所做的更改。
    • 在延迟加载中定义模块,每个模块都有自己的路由模块。你只在应用模块中定义主模块,而不是所有子模块
    猜你喜欢
    • 1970-01-01
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多