Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Der Angular Router im Detail betrachtet

Der Angular Router im Detail betrachtet

Talk from AngularDays in Berlin (Germany), October 2017

15934fa2aa7b2ce21f091e9b7cffa856?s=128

Manfred Steyer
PRO

October 10, 2017
Tweet

Transcript

  1. Der neue Angular Router im Detail betrachtet Manfred Steyer SOFTWAREarchitekt.at

    ManfredSteyer ManfredSteyer
  2. Über mich … • Manfred Steyer • SOFTWAREarchitekt.at • Trainer

    & Consultant • Focus: Angular • Gründer: angular-akademie.com • Google Developer Expert (GDE) Page ▪ 2 Manfred Steyer
  3. Ziel • Den Router kennen lernen • Erweiterte Möglichkeiten kennen

    lernen
  4. Inhalt • Basics zu Routing • Child-Routes • Aux-Routes •

    Guards • Resolver • Lazy Loading • Preloading Page ▪ 4
  5. Didaktik • Präsentation • Live Coding

  6. Motivation Der Router ist der Dreh- und Angelpunkt vieler SPA

  7. Routing Basics Page ▪ 7

  8. Routing unter Angular Page ▪ 8 Logo + Menü Menü

    2 Fußzeile SPA Platzhalter
  9. Routing unter Angular Page ▪ 9 Logo + Menü Menü

    2 Fußzeile SPA Passagier- Komponente /FlugDemo#passagier
  10. Routen via Hash-Fragment • /FlugDemo#passagier • Hash-Fragment wird nie zum

    Server gesendet Page ▪ 10
  11. Routen via History API • /FlugDemo/passagier • Gesamte Url wird

    zum Server gesendet • Server antwortet mit SPA • Server kann erste Ansicht "vorrendern" • Performance, SEO, … • SPA informiert Browser über Grenze zwischen (eigentlicher) Url und Route Page ▪ 11
  12. Parameter • passagier/7 • passagier/7?details=true&page=7 • passagier/7;details=true;page=7 • passagier/7;details=true;page=7/fluege Page

    ▪ 12
  13. Konfiguration Page ▪ 13 const APP_ROUTES: Routes = [ {

    path: 'home', component: HomeComponent }, { path: 'flug-suchen', component: FlugSuchenComponent } ]
  14. Konfiguration Page ▪ 14 const APP_ROUTES: Routes = [ {

    path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', component: HomeComponent }, { path: 'flug-suchen', component: FlugSuchenComponent } ]
  15. Konfiguration Page ▪ 15 const APP_ROUTES: Routes = [ {

    path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', component: HomeComponent }, […] { path: '**', redirectTo: 'home' } ]
  16. Konfiguration Page ▪ 16 // app.module.ts @NgModule({ imports: [ BrowserModule,

    HttpModule, FormsModule, RouterModule.forRoot(ROUTE_CONFIG) ], […] }) export class AppModule { } Für Root-Module Für Feature-Module: forChild
  17. AppComponent Page ▪ 17 @Component({ selector: 'app', templateUrl: './app.component.html' })

    export class App { […] }
  18. View von AppComponent Page ▪ 19 <a routerLink="/">Home</a> <a routerLink="/flug-suchen">Flug

    suchen</a> <div> <router-outlet></router-outlet> </div>
  19. Routen mit Parameter Page ▪ 21

  20. Konfiguration Page ▪ 22 const APP_ROUTES: Routes = [ […]

    { path: 'flug-suchen', component: FlugSuchenComponent }, { path: 'flug-edit/:id', component: FlugEditComponent } }
  21. Parameter auslesen Page ▪ 23 export class FlugEditComponent { public

    id: string; constructor( private route: ActivatedRoute) { route.params.subscribe( p => { this.id = p['id']; […] } ); } […] }
  22. Links auf Routen mit Parameter Page ▪ 24 <a [routerLink]="['/flug-edit',

    flug.id]">Edit</a>
  23. DEMO Page ▪ 25 App Home Search Flight Edit Flight

    Search Passenger Your Bookings FlightBookingModule AppModule
  24. Hierarchisches Routing Page ▪ 26

  25. Hierarchische Views Page ▪ 27 Logo + Menü Menü 2

    Fußzeile SPA Platzhalter 1
  26. Hierarchische Views Page ▪ 28 Logo + Menü Menü 2

    Fußzeile SPA /FlugDemo/flugbuchen FlugBuchen-Komponente
  27. Hierarchische Views Page ▪ 29 Logo + Menü Menü 2

    Fußzeile SPA /FlugDemo/flugbuchen Optionen Platzhalter FlugBuchen-Komponente
  28. Hierarchische Views Page ▪ 30 Logo + Menü Menü 2

    Fußzeile SPA Optionen Passagier- Komponente FlugBuchen-Komponente /FlugDemo/flugbuchen/passagier
  29. Konfiguration Page ▪ 31 const APP_ROUTES: Routes = [ {

    path: '', component: HomeComponent, pathMatch: 'full' }, { path: 'flug-buchen', component: FlugBuchenComponent, children: [ { path: 'flug-suchen', component: FlugSuchenComponent }, […] ] } ];
  30. DEMO Page ▪ 32 App Home Flight- Booking Search Flight

    Edit Flight Search Passenger Your Bookings
  31. Aux-Routes Page ▪ 35

  32. Aux-Routes Page ▪ 36 Logo + Menu Menu 2 Footer

    SPA Placeholder Named Placeholder
  33. Aux-Routes Page ▪ 37 Logo + Menu Menu 2 Footer

    SPA Flight- Component Named Placeholder /FlightApp/flights
  34. Aux-Routes Page ▪ 38 Logo + Menu Menu 2 Footer

    SPA Flight- Component Info-Component /FlightApp/flights(aux:info)
  35. Aux-Routes Page ▪ 39 Logo + Menu Menu 2 Footer

    SPA Flight- Component Modal-Component /FlightApp/flights(aux:info/modal)
  36. Aux-Routes Page ▪ 40 Logo + Menu Menu 2 Footer

    SPA Flight-Edit- Component Modal-Component /FlightApp/flights(aux:info/modal)/17
  37. Use Cases • Modale Dialoge • “Applets” und teilautonome Bereiche

    • Commander-Style Page ▪ 41
  38. Platzhalter definieren Page ▪ 42 <router-outlet></router-outlet> <hr> <router-outlet name="aux"></router-outlet> Standard-Name:

    primary
  39. Konfiguration Page ▪ 43 export const ROUTE_CONFIG: Routes = [

    { path: 'home', component: HomeComponent }, { path: 'info', component: InfoComponent, outlet: 'aux' }, { path: 'dashboard', component: DashboardComponent, outlet: 'aux' } ]
  40. Aux-Routes routen Page ▪ 44 <a [routerLink]="[{outlets: { aux: 'info'

    }}]"> Activate Info </a> <a [routerLink]="[{outlets: { aux: null }}]"> Deactivate Info </a>
  41. Aux-Routes routen Page ▪ 45 <a [routerLink]="[{outlets: { aux: 'info',

    primary: 'flight-search' }}]"> Activate Info </a> <a [routerLink]="[{outlets: { aux: null }}]"> Deactivate Info </a>
  42. Programmatisch routen Page ▪ 46 export class AppComponent { constructor(private

    router: Router) { } activateInfo() { this.router.navigate([{outlets: { aux: 'info' }}]); } deactivateInfo() { this.router.navigate([{outlets: { aux: null }}]); } }
  43. DEMO Page ▪ 47

  44. Guards Page ▪ 48

  45. Was sind Guards? • Services • Werden beim Aktivieren bzw.

    Deaktivieren einer Route aktiv • Können Aktivierung und Deaktivierung verhindern Page ▪ 49
  46. Guards Rückgabewert: boolean | Observable<boolean> | Promise<boolean> CanActivate canActivate CanActivateChild

    canActivateChild CanLoad canLoad CanDeactivate<T> canDeactivate
  47. Guards in der Konfiguration Page ▪ 52 const APP_ROUTES: Routes

    = [ { path: '/flug-buchen', component: FlugBuchenComponent, canActivate: [AuthGuard], children: [ { path: 'flug-edit/:id', component: FlugEditComponent, canDeactivate: [FlugEditGuard] }, […] ] ] Token
  48. Provider für Guards Page ▪ 53 // app.module.ts @NgModule({ providers:

    [ { provide: FlugEditGuard, useClass: AdvFlightEditGuard } { provide: AuthGuard, useClass: AdvAuthGuard } ], […] }) export class AppModule { }
  49. Provider für Guards Page ▪ 54 // app.module.ts @NgModule({ providers:

    [ FlugEditGuard, AuthGuard ], […] }) export class AppModule { }
  50. DEMO Page ▪ 55

  51. Resolver

  52. Was sind Resolver? • Services • Werden beim Routenwechsel aktiv

    • Laden benötigte Daten • Verzögern Aktivierung der neuen Route • Zwischenzeitlich kann z. B. Loading Indikator angezeigt werden
  53. Resolver @Injectable() export class FlightResolver implements Resolve<Flight> { constructor(private flightService:

    FlightService) { } resolve(route, state): Observable<Flight> | Promise<Flight> | Flight { return […] } }
  54. Resolver registrieren const FLIGHT_BOOKING_ROUTES: Routes = [ […] { path:

    'flight-edit/:id', component: FlightEditComponent, resolve: { flight: FlightResolver } } ]; Token
  55. Daten entgegennehmen @Component({ … }) export class FlightEditComponent { flight:

    Flight; constructor(private route: ActivatedRoute) { } ngOnInit() { this.route.data.subscribe( data => { this.flight = data['flight']; } ); } }
  56. DEMO

  57. Lazy Loading Page ▪ 63

  58. Warum Lazy Loading? • Module erst bei Bedarf nachladen •

    Verbesserung der Start-Performance Page ▪ 64
  59. Root Module mit Lazy Loading Page ▪ 65 const APP_ROUTE_CONFIG:

    Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', component: HomeComponent }, { path: 'flights', loadChildren: '[…]flight-booking.module#FlightBookingModule' } ];
  60. Routen für Feature Module Page ▪ 66 const FLUG_ROUTES =

    [ { path: '', component: FlugBuchenComponent, […] }, […] } export const FlugRouterModule = RouterModule.forChild(FLUG_ROUTES);
  61. DEMO Page ▪ 67

  62. Preloading Page ▪ 68

  63. Idee • Eventuell später benötigte Module werden mit freien Ressourcen

    vorgeladen • Wird das Modul später tatsächlich benötigt, steht es augenblicklich zur Verfügung Page ▪ 69
  64. Preloading aktivieren Page ▪ 70 export const AppRoutesModule = RouterModule.forRoot(

    ROUTE_CONFIG, { preloadingStrategy: PreloadAllModules });
  65. Lazy Loading und Shared Services Page ▪ 71

  66. DEMO

  67. Lazy Loading und Shared Modules Page ▪ 73 AppModule FlugModule

    SharedModule includes includes (lazy) includes
  68. Lazy Loading und Shared Modules Page ▪ 74 AppModule FlugModule

    SharedModule includes includes (lazy) includes AuthService AuthService
  69. Lazy Loading und Shared Modules Page ▪ 75 AppModule FlugModule

    SharedModule includes includes (lazy) includes AuthService AuthService
  70. Lösung Page ▪ 76 AppModule FlugModule SharedModule includes (lazy) includes

    CoreModule includes includes Core-Module soll nur ins AppModule eingebunden werden Globale Provider, wie AuthService & Shell
  71. DEMO

  72. Lösung (für Libraries) Page ▪ 78 AppModule FlugModule AuthModule includes

    (lazy) CoreModule
  73. Lösung (für Libraries) Page ▪ 79 AppModule FlugModule AuthModule includes

    (lazy) includes (mit Services) CoreModule includes includes (ohne Services) Shell
  74. AuthModule Page ▪ 81 @NgModule({ […], providers: [] }) export

    class AuthModule { }
  75. AuthModule Page ▪ 82 @NgModule({ […], providers: [] }) export

    class AuthModule { static forRoot(): ModuleWithProviders { return { ngModule: AuthModule, providers: [AuthService, […]] } } }
  76. DEMO Page ▪ 83

  77. Zusammenfassung Platzhalter Child Routes Aux Routes Guards Lazy Loading Preloading

  78. Kontakt [mail] manfred.steyer@SOFTWAREarchitekt.at [blog] SOFTWAREarchitekt.at [twitter] ManfredSteyer