溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Angular2中路由與導(dǎo)航的示例分析

發(fā)布時(shí)間:2021-08-19 11:22:52 來(lái)源:億速云 閱讀:172 作者:小新 欄目:web開(kāi)發(fā)

這篇文章主要為大家展示了“Angular2中路由與導(dǎo)航的示例分析”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Angular2中路由與導(dǎo)航的示例分析”這篇文章吧。

導(dǎo)航是很簡(jiǎn)單的,只是不同頁(yè)面之間的切換,路由是實(shí)現(xiàn)導(dǎo)航的一種。

一個(gè)url對(duì)應(yīng)的一個(gè)頁(yè)面,在angular2中是一個(gè)組件。定義一個(gè)規(guī)則。

基礎(chǔ)知識(shí)

大多數(shù)帶路由的應(yīng)用都要在index.html的標(biāo)簽下先添加一個(gè)元素,來(lái)告訴路由器該如何合成導(dǎo)航用的URL。

路由是從@angular/router包中引入的。

路由都是需要進(jìn)行配置的。而這個(gè)配置需要的也就是RouterModule模塊。

一個(gè)路由配置

path中不能用斜線(xiàn)/開(kāi)頭。

這些路由的定義順序是故意如此設(shè)計(jì)的。 路由器使用先匹配者優(yōu)先的策略來(lái)匹配路由,所以,具體路由應(yīng)該放在通用路由的前面。在上面的配置中,帶靜態(tài)路徑的路由被放在了前面,后面是空路徑路由,因此它會(huì)作為默認(rèn)路由。而通配符路由被放在最后面,這是因?yàn)樗亲钔ㄓ玫穆酚?,?yīng)該只在前面找不到其它能匹配的路由時(shí)才匹配它。

const appRoutes: Routes = [
 {
 path:'',// empty path匹配各級(jí)路由的默認(rèn)路徑。 它還支持在不擴(kuò)展URL路徑的前提下添加路由。
 component: DashboardComponent
 },{
 path: 'dashboard',
 component: DashboardComponent
 }, {
 path: 'loopback',
 component: LoopbackComponent
 }, {
 path: 'heroparent',
 component: HeroParentComponent
 }, {
 path:'version',
 component: VersionParentComponent
 }, {
 path: '**',// **代表該路由是一個(gè)通配符路徑。如果當(dāng)前URL無(wú)法匹配上我們配置過(guò)的任何一個(gè)路由中的路徑,路由器就會(huì)匹配上這一個(gè)。當(dāng)需要顯示404頁(yè)面或者重定向到其它路由時(shí),該特性非常有用。
 component: DashboardComponent,
 }
];

export const appRoutingModule: ModuleWithProviders = RouterModule.forRoot(appRoutes);

RouterOutlet - 路由插座

顯示路由器生成的視圖。在展示父路由的位置中的某個(gè)地方展示子路由對(duì)應(yīng)的地方。

路由模塊

最開(kāi)始的路由,我們是直接寫(xiě)在app.module.ts文件中的,像這樣,我們可以實(shí)現(xiàn)簡(jiǎn)單的導(dǎo)航。

import { NgModule }    from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent }   from './app.component';
import { CrisisListComponent } from './crisis-list.component';
import { HeroListComponent } from './hero-list.component';
const appRoutes: Routes = [
 { path: 'crisis-center', component: CrisisListComponent },
 { path: 'heroes', component: HeroListComponent }
];
@NgModule({
 imports: [
 BrowserModule,
 FormsModule,
 RouterModule.forRoot(appRoutes)
 ],
 declarations: [
 AppComponent,
 HeroListComponent,
 CrisisListComponent
 ],
 bootstrap: [ AppComponent ]
})
export class AppModule {
}

但是這樣不方便,所以我們要進(jìn)行路由的分離,重構(gòu)成我們自己的路由模塊。like this:

const appRoutes: Routes = [
 {
 path:'',
 component: DashboardComponent
 },{
 path: 'dashboard',
 component: DashboardComponent
 }, {
 path: 'loopback',
 component: LoopbackComponent
 }, {
 path: 'heroparent',
 component: HeroParentComponent
 }, {
 path:'version',
 component: VersionParentComponent
 }, {
 path: '**',
 component: DashboardComponent,
 }
];

export const appRoutingModule: ModuleWithProviders = RouterModule.forRoot(appRoutes);

同樣我們還可以寫(xiě)多個(gè)路由模塊。但是我們必須在app.module.ts中進(jìn)行imports:[appRoutingModule]。

組件路由

我們需要將一些特征區(qū)域分割開(kāi)來(lái),做成自己?jiǎn)为?dú)的模塊。必如hero模塊。在這里,我們需要hero單獨(dú)的導(dǎo)航,這也就是組件路由。

平級(jí)的路由

@NgModule({
 imports: [
 RouterModule.forChild([
  { path: 'heroes', component: HeroListComponent },
  { path: 'hero/:id', component: HeroDetailComponent },
  { path:'heroform', component: HeroFormComponent },
 ])
 ],
 exports: [
 RouterModule
 ]
})
export class HeroRoutingModule { }

我們還有另外一中類(lèi)型的路由組織方式,路由樹(shù)的形式。

const crisisCenterRoutes: Routes = [
 {
 path: '',
 redirectTo: '/crisis-center',
 pathMatch: 'full'
 }, {
 path: 'crisis-center',
 component: CrisisCenterComponent,
 children: [
  {
  path: '',
  component: CrisisListComponent,
  children: [
   {
   path: ':id',
   component: CrisisDetailComponent,
   },
   {
   path: '',
   component: CrisisCenterHomeComponent
   }
  ]
  }
 ]
 }
];

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

重定向路由

添加一個(gè)redirect路由,它會(huì)把初始的相對(duì)URL(”)悄悄翻譯成默認(rèn)路徑(/crisis-center)。

{
 path: '',
 redirectTo: '/crisis-center',
 pathMatch: 'full'
},

路由守衛(wèi)

簡(jiǎn)介

路由守衛(wèi),應(yīng)用在這個(gè)路由不是對(duì)所有導(dǎo)航都有效的,是有一些前置條件的,只有當(dāng)這些前置條件滿(mǎn)足的時(shí)候,才能被導(dǎo)航到該頁(yè)面。

可以在路由配置中添加守衛(wèi)來(lái)進(jìn)行處理。守衛(wèi)可以返回一個(gè)boolean值,為true時(shí),導(dǎo)航過(guò)程繼續(xù),為false時(shí),導(dǎo)航被取消,當(dāng)然這時(shí)候也可以被導(dǎo)航到其他頁(yè)面。也可以返回返回一個(gè)Observable<boolean>或Promise<boolean>,并且路由器會(huì)等待這個(gè)可觀(guān)察對(duì)象被解析為true或false。

路由器支持多種守衛(wèi)

用CanActivate來(lái)處理導(dǎo)航到某路由的情況。

用CanActivateChild處理導(dǎo)航到子路由的情況。

用CanDeactivate來(lái)處理從當(dāng)前路由離開(kāi)的情況。

用Resolve在路由激活之前獲取路由數(shù)據(jù)。

用CanLoad來(lái)處理異步導(dǎo)航到某特性模塊的情況。

使用規(guī)則

在分層路由的每個(gè)級(jí)別上,我們都可以設(shè)置多個(gè)守衛(wèi)。 路由器會(huì)先按照從最深的子路由由下往上檢查的順序來(lái)檢查CanDeactivate守護(hù)條件。 然后它會(huì)按照從上到下的順序檢查CanActivate守衛(wèi)。 如果任何守衛(wèi)返回false,其它尚未完成的守衛(wèi)會(huì)被取消,這樣整個(gè)導(dǎo)航就被取消了。

CanActivate

使用CanActivate來(lái)處理導(dǎo)航路由,需要在路由配置中,添加導(dǎo)入AuthGuard類(lèi),修改管理路由并通過(guò)CanActivate屬性來(lái)引用AuthGuard。

具體的守衛(wèi)規(guī)則要看AuthGuard類(lèi)的實(shí)現(xiàn)。而AuthGuard 類(lèi)是需要繼承CanActivate 類(lèi)的:export class AuthGuard implements CanActivate {}

import { AuthGuard }    from '../auth-guard.service';

const adminRoutes: Routes = [
 {
 path: 'admin',
 component: AdminComponent,
 canActivate: [AuthGuard], // 重點(diǎn)
 children: [
  {
  path: '',
  children: [
   { path: 'crises', component: ManageCrisesComponent },
   { path: 'heroes', component: ManageHeroesComponent },
   { path: '', component: AdminDashboardComponent }
  ],
  }
 ]
 }
];

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

CanActivateChild 守衛(wèi)自路由

就像我們可以通過(guò)CanActivate來(lái)守衛(wèi)路由一樣,我們也能通過(guò)CanActivateChild守衛(wèi)來(lái)保護(hù)子路由。CanActivateChild守衛(wèi)的工作方式和CanActivate守衛(wèi)很相似,不同之處在于它會(huì)在每個(gè)子路由被激活之前運(yùn)行。我們保護(hù)了管理特性模塊不受未授權(quán)訪(fǎng)問(wèn),也同樣可以在特性模塊中保護(hù)子路由。

這個(gè)使用起來(lái)比較簡(jiǎn)單,只需要在需要守衛(wèi)的子路由的配置上添加即可。而AuthGuard 類(lèi)是需要繼承canActivateChild 類(lèi)的:export class AuthGuard implements canActivateChild {}

const adminRoutes: Routes = [
 {
 path: 'admin',
 component: AdminComponent,
 canActivate: [AuthGuard],
 children: [
  { // 無(wú)組件路由,相當(dāng)于分組
  path: '',
  canActivateChild: [AuthGuard], // 守衛(wèi)子路由
  children: [
   { path: 'crises', component: ManageCrisesComponent },
   { path: 'heroes', component: ManageHeroesComponent },
   { path: '', component: AdminDashboardComponent }
  ]
  }
 ]
 }
];

CanDeactivate 處理未保存的更改

在現(xiàn)實(shí)世界中,我們得先把用戶(hù)的改動(dòng)積累起來(lái)。 我們可能不得不進(jìn)行跨字段的校驗(yàn),可能要找服務(wù)器進(jìn)行校驗(yàn),可能得把這些改動(dòng)保存成一種待定狀態(tài),直到用戶(hù)或者把這些改動(dòng)作為一組進(jìn)行確認(rèn)或撤銷(xiāo)所有改動(dòng)。

當(dāng)用戶(hù)要導(dǎo)航到外面時(shí),該怎么處理這些既沒(méi)有審核通過(guò)又沒(méi)有保存過(guò)的改動(dòng)呢? 我們不能馬上離開(kāi),不在乎丟失這些改動(dòng)的風(fēng)險(xiǎn),那顯然是一種糟糕的用戶(hù)體驗(yàn)。

我們應(yīng)該暫停,并讓用戶(hù)決定該怎么做。如果用戶(hù)選擇了取消,我們就留下來(lái),并允許更多改動(dòng)。如果用戶(hù)選擇了確認(rèn),那就進(jìn)行保存。
在保存成功之前,我們還可以繼續(xù)推遲導(dǎo)航。如果我們讓用戶(hù)立即移到下一個(gè)界面,而保存卻失敗了(可能因?yàn)閿?shù)據(jù)不符合有效性規(guī)則),我們就會(huì)丟失該錯(cuò)誤的上下文環(huán)境。

在等待服務(wù)器的答復(fù)時(shí),我們沒(méi)法阻塞它 —— 這在瀏覽器中是不可能的。 我們只能用異步的方式在等待服務(wù)器答復(fù)之前先停止導(dǎo)航。

我們需要CanDeactivate守衛(wèi)。

Resolve

主要實(shí)現(xiàn)的就是導(dǎo)航前預(yù)先加載路由信息。可以做到,當(dāng)真正需要導(dǎo)航進(jìn)來(lái)這個(gè)詳情頁(yè)面時(shí),是不需要再去獲取數(shù)據(jù)的。是提前加載好的。

服務(wù)可以實(shí)現(xiàn)Resolve守衛(wèi)接口來(lái)同步或異步解析路由數(shù)據(jù)。

CanLoad - 保護(hù)特性模塊的加載

前提

異步路由,只要是懶惰加載特征區(qū)域。這樣做的好處:

  1. 可以繼續(xù)構(gòu)建特征區(qū),但不再增加初始包大小。

  2. 只有在用戶(hù)請(qǐng)求時(shí)才加載特征區(qū)。

  3. 為那些只訪(fǎng)問(wèn)應(yīng)用程序某些區(qū)域的用戶(hù)加快加載速度。

路由器用loadChildren屬性來(lái)映射我們希望惰性加載的捆文件,這里是AdminModule。

const appRoutes: Routes = [

 {

 path: 'admin',

 loadChildren: 'app/admin/admin.module#AdminModule',

 }

];

映射到了我們以前在管理特性區(qū)構(gòu)建的admin.module.ts 文件。在文件路徑后面,我們使用# 來(lái)標(biāo)記出文件路徑的末尾,并告訴路由器AdminModule 的名字。打開(kāi)admin.module.ts 文件,我們就會(huì)看到它正是我們所導(dǎo)出的模塊類(lèi)的名字。

export class AdminModule {}

簡(jiǎn)介

我們已經(jīng)使CanAcitvate保護(hù)AdminModule了,它會(huì)阻止對(duì)管理特性區(qū)的匿名訪(fǎng)問(wèn)。我們?cè)谡?qǐng)求時(shí)可以異步加載管理類(lèi)路由,檢查用戶(hù)的訪(fǎng)問(wèn)權(quán),如果用戶(hù)未登錄,則跳轉(zhuǎn)到登陸頁(yè)面。但更理想的是,我們只在用戶(hù)已經(jīng)登錄的情況下加載AdminModule,并且直到加載完才放行到它的路由。

我們可以用CanLoad守衛(wèi)來(lái)保證只在用戶(hù)已經(jīng)登錄并嘗試訪(fǎng)問(wèn)管理特性區(qū)時(shí)才加載一次AdminModule。

幾個(gè)概念

無(wú)組件路由

無(wú)組件路由,不借助組件對(duì)路由進(jìn)行分組。來(lái)看AdminComponent
下的子路由,我們有一個(gè)帶path和children的子路由,但它沒(méi)有使用component。這并不是配置中的失誤,而是在使用無(wú)組件路由。

const adminRoutes: Routes = [
 {
 path: 'admin',
 component: AdminComponent,
 children: [
  { // 無(wú)組件路由
  path: '',
  children: [
   { path: 'crises', component: ManageCrisesComponent },
   { path: 'heroes', component: ManageHeroesComponent },
   { path: '', component: AdminDashboardComponent }
  ]
  }
 ]
 }
];

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

預(yù)加載: 在后臺(tái)加載特征區(qū)域

每次導(dǎo)航成功發(fā)生時(shí),路由器將查看惰性加載的特征區(qū)域的配置,并根據(jù)提供的策略作出反應(yīng)。 路由器默認(rèn)支持兩種預(yù)加載策略:

  1. 完全不預(yù)加載,這是默認(rèn)值。惰性加載特征區(qū)域仍然按需加載。

  2. 預(yù)加載所有惰性加載的特征區(qū)域。

路由器還支持自定義預(yù)加載策略,用來(lái)精細(xì)控制預(yù)加載。

自定義預(yù)加載策略

Route Data 啟動(dòng)預(yù)加載

其中有參數(shù)preload布爾值,如果它為true,就調(diào)用內(nèi)置Router

提供的load函數(shù)預(yù)主動(dòng)加載這些特征模塊。

創(chuàng)建自定義策略

我們將需要實(shí)現(xiàn)抽象類(lèi)PreloadingStrategy和preload方法。在異步加載特征模塊和決定是否預(yù)加載它們時(shí),路由器調(diào)用preload方法。 preload方法有兩個(gè)參數(shù),第一個(gè)參數(shù)Route提供路由配置,第二個(gè)參數(shù)是預(yù)加載特征模塊的函數(shù)。

鏈接參數(shù)數(shù)組

鏈接參數(shù)數(shù)組保存路由導(dǎo)航時(shí)所需的成分:

  1. 指向目標(biāo)組件的那個(gè)路由的路徑(path)

  2. 必備路由參數(shù)和可選路由參數(shù),它們將進(jìn)入該路由的URL

e.g.我們可以把RouterLink指令綁定到一個(gè)數(shù)組,就像這樣:

<a [routerLink]="['/heroes']">Heroes</a>

e.g.在指定路由參數(shù)時(shí),我們寫(xiě)過(guò)一個(gè)雙元素的數(shù)組,就像這樣:

this.router.navigate(['/hero', hero.id]);

e.g.我們可以在對(duì)象中提供可選的路由參數(shù),就像這樣:

<a [routerLink]="['/crisis-center', { foo: 'foo' }]">Crisis Center</a>

以上是“Angular2中路由與導(dǎo)航的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI