Angular4 開發(fā)實戰(zhàn):(10) 路由導(dǎo)航(Router)

2018-06-19 11:26 更新
路由是Angular導(dǎo)航的關(guān)鍵。

<base href> 在設(shè)置路由之前,我們需要在app/index.html添加路由說明。 由于當(dāng)前項目的根目錄是app,所以添加如下代碼:

<base href="/">

路由模塊已經(jīng)從Angular中分離出來,所以我們在使用時要導(dǎo)入:

import { RouterModule, Routes } from '@angular/router';

現(xiàn)在可以來寫一個簡單的路由配置,我們將路由放置到一個模塊中:

// app/modules/app-routing.module.ts   

import { NgModule } from '@angular/core';  

import {Routes, RouterModule} from '@angular/router';  

import {DemoComponentComponent} from '../demo/demo-component/demo-component.component';   


const routes: Routes = [   

  { path: 'demoComponent', component: DemoComponentComponent},   

  ...   

  { path: '**', component: DemoComponentComponent }  

];   


@NgModule({   

  imports: [   

    RouterModule.forRoot(routes)   

  ],   

  exports: [RouterModule]  

})  

export class AppRoutingModule { }

在上面的代碼中,我們定義了一個路由數(shù)組,每一個都會把一個URL路徑(path)映射到一個組件。 最后的**是路由通配符,當(dāng)所有其上面的路由路徑都不符合(包括無效路徑)時,就會采取通配符路由。 注意:
  • 在特性模塊中,應(yīng)該使用RouterModule.forChild()
  • path不能以斜杠(/)開頭
定義好路由模塊后,我們還需要將其注冊到主模塊:

// app.module.ts   

...   

import { AppComponent } from './app.component';  

import {AppRoutingModule} from './modules/app-routing.module';   


@NgModule({   

  ...   

  imports: [   

    ...   

    AppRoutingModule   

  ],   

  providers: [],   

  bootstrap: [AppComponent]  

})  

export class AppModule { }

有了路由導(dǎo)航,我們還需要一個容器來顯示對應(yīng)的組件內(nèi)容:

<router-outlet></router-outlet>

添加如上代碼后,當(dāng)路由切換(路由模塊中存在的路由)時,對應(yīng)的組件會顯示在其之后。 注:可以參考app/app.component.html。 注(來源官網(wǎng)):路由器使用先匹配者優(yōu)先的策略來匹配路由,所以,具體路由應(yīng)該放在通用路由的前面。在上面的配置中,帶靜態(tài)路徑的路由被放在了前面,后面是空路徑路由,因此它會作為默認路由。而通配符路由被放在最后面,這是因為它能匹配上每一個URL,因此應(yīng)該只有在前面找不到其它能匹配的路由時才匹配它。 既然是路由導(dǎo)航,除了可以直接在瀏覽器的地址欄輸入地址跳轉(zhuǎn)外,我們更多時候需要一系列可以點擊的鏈接元素(比如a,button):

<a routerLink="/demoComponent">創(chuàng)建組件</a>

由于導(dǎo)航路徑是固定的,所以我們將一個字符串賦給routerLink。 注:a標簽上的RouterLink指令讓路由器得以控制這個a元素。 當(dāng)然,如果我們需要更復(fù)雜的路由路徑,我們可以使用鏈接參數(shù)數(shù)組:

[routerLink] = ['/demoComponent', 'id']   


[routerLink] = ['/demoComponent', { name: 'route', id: 123}]

一般情況下,我們會為當(dāng)前激活的路徑鏈接添加一些高亮效果,這時我們可以利用routerLinkActive屬性:

<a routerLink="/demoComponent" routerLinkActive="active">創(chuàng)建組件</a>

它的值是一個以空格分割的CSS樣式類列表。 還可以是一個CSS類數(shù)組:

[routerLinkActive]="['...']"

注(來源官網(wǎng)):RouterLinkActive指令會基于當(dāng)前的RouterState對象來為激活的RouterLink切換CSS類。 這會一直沿著路由樹往下進行級聯(lián)處理,所以父路由鏈接和子路由鏈接可能會同時激活。 要改變這種行為,可以把[routerLinkActiveOptions]綁定到{exact: true}表達式。 如果使用了{ exact: true },那么只有在其URL與當(dāng)前URL精確匹配時才會激活指定的RouterLink。 重定向 在路由配置中,我們還可以添加重定向參數(shù):

{ path: '', redirectTo: '/demoComponent', pathMatch: 'full' }

注:重定向路由需要一個pathMatch屬性,來告訴路由器如何用URL去匹配路由的路徑,否則路由器就會報錯。 路由參數(shù) 在配置路由時,我們還可以定義路由參數(shù):

// app/modules/app-routing.module.ts   


{ path: 'demoRouter/:id', component: DemoRouterComponent}

比如輸入http://localhost:4200/demoRouter/123,然后我們需要通過ActivatedRoute服務(wù)來獲取這些路由參數(shù):

// demo-router.component.ts   

import { Component, OnInit } from '@angular/core';  

import {ActivatedRoute} from '@angular/router';   

...


export class DemoRouterComponent implements OnInit {    

  id: any;   

  constructor(private route: ActivatedRoute) {   

    this.route.params.subscribe(param => {   

      this.id = param['id'];   

    })   

  }      

...  

}

在上面的代碼中,我們注入ActivatedRoute服務(wù)并定義了一個私有屬性route,然后通過route.params屬性來獲取路由參數(shù),ActivatedRoute.params是一個路由參數(shù)的可觀察對象,所以我們要通過subscribe()方法來訪問。 注:所有的路由參數(shù)或查詢參數(shù)都是字符串。 子路由 子路由也是我們常用的,定義也很簡單:

// app/modules/app-routing.module.ts   

import {DemoChildRouterComponent} from '../demo/demo-child-router/demo-child-router.component';   


const routes: Routes = [   

  ...   

  {   

    path: 'demoRouter2', component: DemoRouter2Component,   

    children: [{   

      path: 'child',   

      component: DemoChildRouterComponent   

    }]   

  }  

];

子路由組件:

// app/demo/demo-child-router.component.html   

<div class="box">   

  我是子路由  

</div>

前面說過我們要給路由添加視圖容器,子路由也是一樣,不過子路由的視圖容器要放在另一個組件中:

// app/demo/demo-router2.component.html   

<div class="box">   

  <a routerLink="/demoRouter2/child">訪問子路由</a>  

</div>   


<router-outlet></router-outlet>

當(dāng)我們點擊上面的鏈接時,你會看到瀏覽器地址欄變?yōu)椋?b>http://localhost:4200/demoRouter2/child,組件DemoChildRouterComponent中的模板就會顯示出來。 路由動畫 對于路由,我們還可以添加動畫,但使用動畫之前,我們要安裝動畫模塊(Angular4后動畫模塊分離出來了):

npm install @angular/animations --save

然后在主模塊app.module.ts中注冊:

...   

import {BrowserAnimationsModule} from '@angular/platform-browser/animations';   


@NgModule({   

  declarations: [... ],   

  imports: [   

    ...   

    BrowserAnimationsModule   

  ],   

  providers: [],   

  bootstrap: [AppComponent]  

})  

export class AppModule { }

我們添加一個具有動畫的子路由:

// app/modules/app-routing.module.ts   

import {DemoChildRouter2Component} from '../demo/demo-child-router/demo-child-router2.component';   


const routes: Routes = [   

  ...   

  {   

    path: 'demoRouter2', component: DemoRouter2Component,   

    children: [   

     ...   

     {   

       path: 'child2',   

       component: DemoChildRouter2Component   

    }]   

  }  

];

對于DemoChildRouter2Component組件,我們修改如下:

// demo/demo-child-router2.component.html   

import {Component, HostBinding, OnInit} from '@angular/core';  

import {animate, state, style, trigger, transition} from '@angular/animations';   


@Component({   

  selector: 'app-demo-child-router2',   

  templateUrl: './demo-child-router2.component.html',   

  styleUrls: ['./demo-child-router2.component.scss'],   

  animations: [    

    trigger('fadeInUpState', [   

      state('in', style({opacity: 1, transform: 'translate3d(0, 0, 0)'})),   

      transition('void => *', [   

        style({   

          opacity: 0,   

          transform: 'translate3d(0, 100%, 0)'   

        }), animate('.4s cubic-bezier(.25,.8,.25,1)')   

     ])   

    ])   

  ]  

})  


export class DemoChildRouter2Component implements OnInit {   

  @HostBinding('@fadeInUpState') fadeInUpState;   

  @HostBinding('style.display') display = 'block';   

  constructor() { }  

}

對于@HostBinding()是屬性裝飾器,用來給宿主設(shè)置屬性。在這里我們將動畫@fadeInUpState添加到宿主上,同時還將宿主的display的值設(shè)置為block。 注意:給宿主添加動畫,一定要設(shè)置`display`的值,因為默認自定義元素的display是空字符串,CSS動畫是不起作用的。 關(guān)于動畫的更多細節(jié),可以看《動畫(Animation)》一章。 異步路由 隨著項目越來越大,我們一般不會將所有組件都添加到主模塊中,這時我們可以根據(jù)不同路由的;奧惰性加載不同的模塊:

const routes: Routes = [   

  ...   

  {   

    path: 'demoRouter2',   

    component: DemoRouter2Component,   

    children: [   

      ...   

     {   

       path: 'loadModule',   

       loadChildren: 'app/demo/demo-router-load.module#RouterLoadModule',   

    }]   

  }  

];

當(dāng)路由器導(dǎo)航到這個路由時,它會用loadChildren字符串來動態(tài)加載RouterLoadModule,然后把RouterLoadModule添加到當(dāng)前的路由配置中, 最后,它把所請求的路由加載到目標DemoRouterLoadComponent組件中。 RouterLoadModule代碼如下:

import {NgModule} from '@angular/core';  

import {CommonModule} from '@angular/common';  

import {DemoRouterLoadComponent} from './demo-router-load.component';  

import {DemoRouterLoadRougingModule} from './demo-router-load-routing.module';   


@NgModule({   

  imports: [CommonModule, DemoRouterLoadRougingModule],   

  declarations: [DemoRouterLoadComponent]  

})   


export class RouterLoadModule {}

仔細看的話,你會發(fā)現(xiàn)一個新的子路由模塊DemoRouterLoadRougingModule,它是用來加載異步路由配置的:

// demo-router-load-routing.module.ts   

import {NgModule} from '@angular/core';  

import {RouterModule, Routes} from '@angular/router';  

import {DemoRouterLoadComponent} from './demo-router-load.component';   


const routes: Routes = [   

  {   

    path: '',   

    component: DemoRouterLoadComponent   

  }  

]  


@NgModule({   

  imports: [RouterModule.forChild(routes)],   

  exports: [RouterModule]  

})   


export class DemoRouterLoadRougingModule {}

使用:

// demo-router2.component.html   

<a routerLink="/demoRouter2/loadModule">訪問異步路由</a>

當(dāng)你點擊上面的鏈接時,你可以打開控制臺看看Network看看會多了一個加載文件: 注:惰性加載和重新配置工作只會發(fā)生一次,也就是在該路由首次被請求時。在后續(xù)的請求中,該模塊和路由都是立即可用的。

如發(fā)現(xiàn)任何問題或有好的建議,歡迎在下方評論留言。
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號