Angular2學(xué)習(xí)筆記——詳解路由器模型(Router)
Angular2以組件化的視角來看待web應(yīng)用,使用Angular2開發(fā)的web應(yīng)用,就是一棵組件樹。組件大致分為兩類:一類是如list、table這種通放之四海而皆準(zhǔn)的通用組件,一類是專為業(yè)務(wù)開發(fā)的業(yè)務(wù)組件。實(shí)際開發(fā)中大部分時間我們都需要處理業(yè)務(wù)組件。對于SPA應(yīng)用來說,一個通用的問題就是如何控制頁面的切換,解決這個問題的通用方法就是利用路由器來實(shí)現(xiàn)。
路由配置
現(xiàn)在我們先撇開Angular2來看看通用的路由器模型。通常來講SPA應(yīng)用需要路由配置信息:
[ { path: '', pathMatch: 'full', redirectTo: '/inbox' }, { path: ':folder', children: [ { path: '', component: ConversationsCmp }, { path: ':id', component: ConversationCmp, children: [ { path: 'messages', component: MessagesCmp }, { path: 'messages/:id', component: MessageCmp } ] } ] }, { path: 'compose', component: ComposeCmp, outlet: 'popup' }, { path: 'message/:id', component: PopupMessageCmp, outlet: 'popup' } ]
這個配置信息定義了應(yīng)用的潛在路由狀態(tài)(Router State)。一個路由狀態(tài)代表了一份組件布置信息。 現(xiàn)在我們換一個視角來看這份配置:
在這棵配置樹中,每一個節(jié)點(diǎn)就是一個路由,它對應(yīng)了一個組件。
路由狀態(tài)
在路由樹這種視角下,每一個路由狀態(tài)就是配置樹的一棵子樹。下圖中的路由狀態(tài)下,最終被激活的組件是ConversationCmp:
導(dǎo)航
路由器的首要任務(wù)就是控制在不同路由狀態(tài)之間導(dǎo)航以及更新組件樹。如下圖所示,當(dāng)我們導(dǎo)航到另一個頁面時,路由狀態(tài)也會發(fā)生改變,隨之頁面上顯示的組件也跟隨變化。
到此為止路由器的基本模型已經(jīng)介紹完畢,下面我們來看一下Angular2中的路由模型。
Angular2路由處理流程
Angular2對待一個URL的處理流程為:
1.應(yīng)用重定向
2.識別路由狀態(tài)
3.應(yīng)用哨兵與傳遞數(shù)據(jù)
4.激活對應(yīng)組件
重定向
假設(shè)我們訪問的地址是:http://hostname/inbox/33/message/44。路由器首先根據(jù)配置規(guī)則:
{ path: ‘', pathMatch: ‘full', redirectTo: ‘/inbox' }
來判斷是否需要重定向,如果我們的url是http://hostname/此時,就是重定向到http://hostname/inbox,根據(jù)配置規(guī)則:folder,這時候被激活的組件就是ConversationComp。但現(xiàn)在我們的url是http://hostname/inbox/33/message/44,所以不會發(fā)生重定向。
識別路由狀態(tài)
接下來路由器會為這個URL分發(fā)一個路由狀態(tài)。根據(jù)配置規(guī)則
{ path: ':folder', children: [ { path: '', component: ConversationsCmp }, { path: ':id', component: ConversationCmp, children: [ { path: 'messages', component: MessagesCmp }, { path: 'messages/:id', component: MessageCmp } ] } ] }
/inbox/33/message/44首先匹配:folder,對應(yīng)組件為ConversationCmp,而后進(jìn)入子配置,'message/:id',MessageCmp組件被激活。
根據(jù)上圖的狀態(tài)樹,我們可以看出MessageCmp與ConversationCmp對應(yīng)的路由狀態(tài)。與此同時一個被稱為激活路由(ActivatedRoute)的對象將被創(chuàng)建,并可以在MessageCmp訪問到,通過ActivatedRoute我們可以拿到它的routerState屬性,通過路由狀態(tài)我們可以拿到具體參數(shù)如id對應(yīng)的44。從此也可以看出拿到父級參數(shù)id(33)就必須訪問父級的路由狀態(tài)。
ngOnInit() { this.sub = this.router.routerState.parent(this.route).params.subscribe(params => { this.parentRouteId = +params["id"]; }); }
哨兵與分發(fā)數(shù)據(jù)
哨兵的作用是判斷是否允許應(yīng)用在不同狀態(tài)間進(jìn)行切換,比如:如果用戶沒有登陸就不允許進(jìn)入Message頁面。哨兵可以用來判斷是否允許進(jìn)入本路由狀態(tài),是否允許離開本路由狀態(tài)。下例中的CanActivate用來判斷是否允許進(jìn)入,這個服務(wù)類需要繼承CanActivate接口。
import { AuthGuard } from '../auth-guard.service'; const adminRoutes: Routes = [ { path: 'admin', component: AdminComponent, canActivate: [AuthGuard], children: [ { path: '', children: [ { path: 'crises', component: ManageCrisesComponent }, { path: 'heroes', component: ManageHeroesComponent }, { path: '', component: AdminDashboardComponent } ], } ] } ]; export const adminRouting: ModuleWithProviders = RouterModule.forChild(adminRoutes);
import { Injectable } from '@angular/core'; import { CanActivate } from '@angular/router'; @Injectable() export class AuthGuard implements CanActivate { canActivate() { console.log('AuthGuard#canActivate called'); return true; } }
哨兵內(nèi)容涉及到另一個部分知識,所以我會把他放到下一篇文章中。
Angular2的路由器允許我們在進(jìn)入組件中拿到除當(dāng)前路由參數(shù)之外的其他信息。在路由配置中使用resolve屬性指定一個數(shù)據(jù)分發(fā)器。
[ { path: ':folder', children: [ { path: '', component: ConversationsCmp, resolve: { conversations: ConversationsResolver } } ] } ]
數(shù)據(jù)分發(fā)器需要繼承DataResolver接口:
@Injectable() class ConversationsResolver implements DataResolver { constructor(private repo: ConversationsRepo, private currentUser: User) {} resolve(route: ActivatedRouteSnapshot, state: RouteStateSnapshot): Promise<Conversation[]> { return this.repo.fetchAll(route.params['folder'], this.currentUser); } }
還需要把這個數(shù)據(jù)分發(fā)器加入到module的Providers中:
@NgModule({ //... providers: [ConversationsResolver], bootstrap: [MailAppCmp] }) class MailModule { } platformBrowserDynamic().bootstrapModule(MailModule);
而后我們在組件中就可以通過ActivatedRoute來訪問分發(fā)數(shù)據(jù)了。
@Component({ template: ` <conversation *ngFor="let c of conversations | async"></conversation> ` }) class ConversationsCmp { conversations: Observable<Conversation[]>; constructor(route: ActivatedRoute) { this.conversations = route.data.pluck('conversations'); } }
激活組件
此時路由器根據(jù)路由狀態(tài)來實(shí)例化組件并把他們放到合適的路由組出發(fā)點(diǎn)上。
@Component({ template: ` ... <router-outlet></router-outlet> ... <router-outlet name="popup"></router-outlet> ` }) class MailAppCmp { }
如‘/inbox/33/message/44(popup:compose)',首先實(shí)例化ConversationCmp放到主<router-outlet>中,然后實(shí)例化MessageCmp放到name為popup的<Router-outlet>中。
現(xiàn)在路由器對URL的解析過程完畢。但是如果用戶想從MessageCmp中跳轉(zhuǎn)到別的路由狀態(tài)該如何做呢?Angular2提供了兩種方式。
一種是通過router.navigate方法來導(dǎo)航:
@Component({...}) class MessageCmp { private id: string; constructor(private route: ActivatedRoute, private router: Router) { route.params.subscribe(_ => this.id = _.id); } openPopup(e) { this.router.navigate([{outlets: {popup: ['message', this.id]}}]).then(_ => { // navigation is done }); } }
一種是利用router-link方式:
@Component({ template: ` <a [routerLink]="['/', {outlets: {popup: ['message', this.id]}}]">Edit</a> ` }) class MessageCmp { private id: string; constructor(private route: ActivatedRoute) { route.params.subscribe(_ => this.id = _.id); } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Angular 2父子組件之間共享服務(wù)通信的實(shí)現(xiàn)
這篇文章主要給大家介紹了關(guān)于Angular 2父子組件之間共享服務(wù)通信的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-07-07AngularJS 應(yīng)用身份認(rèn)證的技巧總結(jié)
這篇文章主要介紹了AngularJS 應(yīng)用身份認(rèn)證的技巧總結(jié),具有一定的參考價值,有需要的可以了解一下。2016-11-11總結(jié)AngularJS開發(fā)者最常犯的十個錯誤
AngularJS是如今最受歡迎的JS框架之一,簡化開發(fā)過程是它的目標(biāo)之一,這使得它非常適合于元型較小的apps的開發(fā),但也擴(kuò)展到具有全部特征的客戶端應(yīng)用的開發(fā)。下面給大家總結(jié)了AngularJS開發(fā)者最常犯的十個錯誤,有需要的可以參考學(xué)習(xí)下。2016-08-08AngularJs點(diǎn)擊狀態(tài)值改變背景色的實(shí)例
下面小編就為大家分享一篇AngularJs點(diǎn)擊狀態(tài)值改變背景色的實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12AngularJS雙向綁定和依賴反轉(zhuǎn)實(shí)例詳解
這篇文章主要介紹了AngularJS雙向綁定和依賴反轉(zhuǎn)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04