Angular 路由的完整指南

已發表: 2022-03-10
快速總結↬在本教程中,Ahmed Bouchefra 介紹了 Angular Router 以及如何使用它來創建具有路由和導航的客戶端應用程序和單頁應用程序。

如果您還不太熟悉 Angular 7,我想讓您更接近這個令人印象深刻的前端框架所提供的一切。 我將引導您完成一個 Angular 演示應用程序,該應用程序顯示與路由器相關的不同概念,例如:

  • 路由器插座,
  • 路線和路徑,
  • 導航。

我還將向您展示如何使用 Angular CLI v7 生成一個演示項目,我們將在其中使用 Angular 路由器來實現路由和導航。 但首先,請允許我向您介紹 Angular 並回顧其最新版本中的一些重要新功能。

介紹 Angular 7

Angular 是用於為移動和桌面 Web 構建客戶端 Web 應用程序的最流行的前端框架之一。 它遵循基於組件的架構,其中每個組件都是獨立且可重用的代碼,用於控制應用程序 UI 的一部分。

Angular 中的組件是一個使用@Component裝飾器裝飾的 TypeScript 類。 它有一個附加的模板和構成組件視圖的 CSS 樣式表。

Angular 7 是 Angular 的最新版本,最近發布了新功能,特別是在 CLI 工具和性能方面,例如:

  • CLI 提示:像ng addng new這樣的常用命令現在可以提示用戶選擇要添加到項目中的功能,如路由和样式表格式等。
  • 向 Angular Material CDK(組件 DevKit)添加滾動。
  • 向 Angular Material CDK 添加拖放支持。
  • 項目也默​​認使用預算包,當他們的應用程序超過大小限制時,它會警告開發人員。 默認情況下,當大小超過 2MB 並且錯誤為 5MB 時會引發警告。 您還可以在angular.json文件中更改這些限制。 等等。
跳躍後更多! 繼續往下看↓

介紹 Angular 路由器

Angular Router 是一個強大的 JavaScript 路由器,由 Angular 核心團隊構建和維護,可以從@angular/router包中安裝。 它提供了一個完整的路由庫,可以有多個路由器出口、不同的路徑匹配策略、輕鬆訪問路由參數和路由保護以保護組件免受未經授權的訪問。

Angular 路由器是 Angular 平台的核心部分。 它使開發人員能夠構建具有多個視圖的單頁應用程序,並允許在這些視圖之間導航。

現在讓我們更詳細地了解基本的路由器概念。

路由器插座

Router-Outlet是一個可從路由器庫中獲得的指令,路由器在其中插入根據當前瀏覽器的 URL 匹配的組件。 您可以在 Angular 應用程序中添加多個插座,從而實現高級路由場景。

 <router-outlet></router-outlet>

任何被路由器匹配的組件都會將其渲染為路由器出口的兄弟。

路線和路徑

路由是由至少一個路徑和一個組件(或重定向到路徑)屬性組成的定義(對象)。 路徑是指 URL 中決定應該顯示的唯一視圖的部分,組件是指需要與路徑關聯的 Angular 組件。 基於我們提供的路由定義(通過靜態RouterModule.forRoot(routes)方法),路由器能夠將用戶導航到特定視圖。

每個Route都將一個 URL path映射到一個組件。

路徑可以為空,表示應用程序的默認路徑,通常是應用程序的開始。

路徑可以採用通配符字符串 ( ** )。 如果請求的 URL 與定義的路由的任何路徑都不匹配,路由器將選擇此路由。 這可用於顯示“未找到”視圖或在未找到匹配項時重定向到特定視圖。

這是一個路由示例:

 { path: 'contacts', component: ContactListComponent}

如果將此路由定義提供給路由器配置,則當 Web 應用程序的瀏覽器 URL 變為/contacts時,路由器將呈現ContactListComponent

路由匹配策略

Angular Router 提供了不同的路由匹配策略。 默認策略只是檢查當前瀏覽器的 URL 是否以path為前綴。

例如我們之前的路線:

 { path: 'contacts', component: ContactListComponent}

也可以寫成:

 { path: 'contacts',pathMatch: 'prefix', component: ContactListComponent}

patchMath屬性指定匹配策略。 在這種情況下,它的前綴是默認值。

第二個匹配策略是滿的。 當為路由指定時,路由器將檢查該路徑是否與當前瀏覽器 URL 的路徑完全相同:

 { path: 'contacts',pathMatch: 'full', component: ContactListComponent}

路由參數

使用參數創建路由是 Web 應用程序中的常見功能。 Angular Router 允許您以不同的方式訪問參數:

  • 使用 ActivatedRoute 服務,
  • 使用從 v4 開始可用的 ParamMap observable。

您可以使用冒號語法創建路由參數。 這是一個帶有id參數的示例路由:

 { path: 'contacts/:id', component: ContactDetailComponent}

路線守衛

路由保護是 Angular 路由器的一項功能,它允許開發人員在請求路由時運行一些邏輯,並基於該邏輯,它允許或拒絕用戶訪問該路由。 它通常用於檢查用戶是否已登錄並獲得授權,然後才能訪問頁面。

您可以通過實現@angular/router包中提供的CanActivate接口來添加路由保護,並擴展canActivate()方法,該方法包含允許或拒絕訪問路由的邏輯。 例如,以下守衛將始終允許訪問路由:

 class MyGuard implements CanActivate { canActivate() { return true; } }

然後,您可以使用canActivate屬性使用警衛保護路由:

 { path: 'contacts/:id, canActivate:[MyGuard], component: ContactDetailComponent}

導航指令

Angular 路由器提供了routerLink指令來創建導航鏈接。 該指令採用與要導航到的組件關聯的路徑。 例如:

 <a [routerLink]="'/contacts'">Contacts</a>

多個網點和輔助路線

Angular Router 在同一個應用程序中支持多個出口。

一個組件有一個關聯的主路由,並且可以有輔助路由。 輔助路線使開發人員能夠同時導航多條路線。

要創建輔助路由,您需要一個命名的路由器出口,其中將顯示與輔助路由關聯的組件。

 <router-outlet></router-outlet> <router-outlet name="outlet1"></router-outlet>
  • 沒有名字的出口是主要出口。
  • 除主要出口外,所有出口都應有名稱。

然後,您可以使用 outlet 屬性指定要在其中呈現組件的出口:

 { path: "contacts", component: ContactListComponent, outlet: "outlet1" }

創建一個 Angular 7 演示項目

在本節中,我們將看到一個如何設置和使用 Angular 路由器的實際示例。 您可以看到我們將要創建的現場演示以及該項目的 GitHub 存儲庫。

安裝 Angular CLI v7

Angular CLI 需要Node 8.9+NPM 5.5.1+ 。 您需要確保在系統上安裝了這些要求,然後運行以下命令來安裝最新版本的 Angular CLI:

 $ npm install -g @angular/cli

這將全局安裝 Angular CLI。

安裝 Angular CLI v7
安裝 Angular CLI v7(大預覽)

注意您可能希望使用sudo全局安裝軟件包,具體取決於您的 npm 配置。

創建一個 Angular 7 項目

創建一個新項目是一個命令,您只需要運行以下命令:

 $ ng new angular7-router-demo

CLI 將詢問您是否要添加路由(輸入N表示否,因為我們將看到如何手動添加路由)以及您要使用哪種樣式表格式,選擇 CSS,第一個選項然後Enter 。 CLI 將創建一個包含必要文件的文件夾結構並安裝項目所需的依賴項。

創建虛假的後端服務

由於我們沒有真正的後端進行交互,我們將使用angular-in-memory-web-api庫創建一個假後端,該庫是一個用於 Angular 演示和測試的內存中 Web API通過 REST API 模擬 CRUD 操作。

它通過攔截發送到遠程服務器的HttpClient請求並將它們重定向到我們需要創建的本地內存數據存儲來工作。

要創建假後端,我們需要執行以下步驟:

  1. 首先,我們安裝angular-in-memory-web-api模塊,
  2. 接下來,我們創建一個返回虛假數據的服務,
  3. 最後,配置應用程序以使用假後端。

在您的終端中運行以下命令以從 npm 安裝angular-in-memory-web-api模塊:

 $ npm install --save angular-in-memory-web-api

接下來,使用以下命令生成後端服務:

 $ ng gs backend

打開src/app/backend.service.ts文件並從angular-in-memory-web-api模塊導入InMemoryDbService

 import {InMemoryDbService} from 'angular-in-memory-web-api'

服務類需要實現InMemoryDbService然後重寫createDb()方法:

 @Injectable({ providedIn: 'root' }) export class BackendService implements InMemoryDbService{ constructor() { } createDb(){ let contacts = [ { id: 1, name: 'Contact 1', email: '[email protected]' }, { id: 2, name: 'Contact 2', email: '[email protected]' }, { id: 3, name: 'Contact 3', email: '[email protected]' }, { id: 4, name: 'Contact 4', email: '[email protected]' } ]; return {contacts}; } }

我們只需創建一個聯繫人數組並返回它們。 每個聯繫人都應該有一個 id。

最後,我們只需要將InMemoryWebApiModule導入app.module.ts文件,並提供我們的假後端服務。

 import { InMemoryWebApiModule } from “angular-in-memory-web-api”; import { BackendService } from “./backend.service”; /* ... */ @NgModule({ declarations: [ /*...*/ ], imports: [ /*...*/ InMemoryWebApiModule.forRoot(BackendService) ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }

接下來創建一個ContactService ,它封裝了用於處理聯繫人的代碼:

 $ ng gs contact

打開src/app/contact.service.ts文件並將其更新為類似於以下代碼:

 import { Injectable } from '@angular/core'; import { HttpClient } from “@angular/common/http”; @Injectable({ providedIn: 'root' }) export class ContactService { API_URL: string = "/api/"; constructor(private http: HttpClient) { } getContacts(){ return this.http.get(this.API_URL + 'contacts') } getContact(contactId){ return this.http.get(`${this.API_URL + 'contacts'}/${contactId}`) } }

我們添加了兩種方法:

  • getContacts()
    用於獲取所有聯繫人。
  • getContact()
    通過 id 獲取聯繫人。

您可以將API_URL設置為任何 URL,因為我們不會使用真正的後端。 所有請求都將被攔截並發送到內存後端。

創建我們的 Angular 組件

在我們了解如何使用不同的路由器功能之前,讓我們首先在我們的項目中創建一堆組件。

前往您的終端並運行以下命令:

 $ ng gc contact-list $ ng gc contact-detail

這將生成兩個ContactListComponentContactDetailComponent組件並將它們添加到主應用程序模塊中。

設置路由

在大多數情況下,您將使用 Angular CLI 創建帶有路由設置的項目,但在這種情況下,我們將手動添加它,以便更好地了解路由在 Angular 中是如何工作的。

添加路由模塊

我們需要添加AppRoutingModule ,它將包含我們的應用程序路由和一個路由器出口,Angular 將根據瀏覽器當前 URL 插入當前匹配的組件。

走著瞧:

  • 如何創建一個用於路由的 Angular 模塊並導入它;
  • 如何為不同的組件添加路由;
  • 如何添加路由器插座。

首先,讓我們首先在app-routing.module.ts文件中創建一個路由模塊。 在src/app中使用以下命令創建文件:

 $ cd angular7-router-demo/src/app $ touch app-routing.module.ts

打開文件並添加以下代碼:

 import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = []; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }

我們首先從@angular/core包中導入NgModule ,這是一個用於創建 Angular 模塊的 TypeScript 裝飾器。

我們還從@angular/router包中導入RouterModuleRoutes類。 RouterModule提供了像RouterModule.forRoot()這樣的靜態方法,用於將配置對像傳遞給路由器。

接下來,我們定義一個Routes類型的常量routes數組,用於保存每條路由的信息。

最後,我們創建並導出一個名為AppRoutingModule的模塊(您可以隨意調用它),它只是一個使用@NgModule裝飾器裝飾的 TypeScript 類,它接受一些元信息對象。 在這個對象的imports屬性中,我們以 routes 數組作為參數調用靜態RouterModule.forRoot(routes)方法。 在RouterModule exports

導入路由模塊

接下來,我們需要將此模塊路由導入到位於src/app/app.module.ts文件中的主應用程序模塊中:

 import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }

我們從./app-routing.module導入AppRoutingModule並將其添加到主模塊的imports數組中。

添加路由器插座

最後,我們需要添加路由器插座。 打開包含主應用模板的src/app/app.component.html文件並添加<router-outlet>組件:

 <router-outlet></router-outlet>

這是 Angular 路由器渲染與當前瀏覽器路徑對應的組件的地方。

這就是我們需要遵循的所有步驟,以便在 Angular 項目中手動設置路由。

創建路由

現在,讓我們為我們的兩個組件添加路由。 打開src/app/app-routing.module.ts文件並將以下路由添加到routes數組:

 const routes: Routes = [ {path: 'contacts' , component: ContactListComponent}, {path: 'contact/:id' , component: ContactDetailComponent} ];

確保在路由模塊中導入這兩個組件:

 import { ContactListComponent } from './contact-list/contact-list.component'; import { ContactDetailComponent } from './contact-detail/contact-detail.component';

現在我們可以從/contactscontact/:id路徑訪問這兩個組件。

添加導航鏈接

接下來讓我們使用routerLink指令將導航鏈接添加到我們的應用模板。 打開src/app/app.component.html並在路由器插座頂部添加以下代碼:

 <h2><a [routerLink] = "'/contacts'">Contacts</a></h2>

接下來我們需要在ContactListComponent中顯示聯繫人列表。 打開src/app/contact-list.component.ts然後添加以下代碼:

 import { Component, OnInit } from '@angular/core'; import { ContactService } from '../contact.service'; @Component({ selector: 'app-contact-list', templateUrl: './contact-list.component.html', styleUrls: ['./contact-list.component.css'] }) export class ContactListComponent implements OnInit { contacts: any[] = []; constructor(private contactService: ContactService) { } ngOnInit() { this.contactService.getContacts().subscribe((data : any[])=>{ console.log(data); this.contacts = data; }) } }

我們創建一個contacts數組來保存聯繫人。 接下來,我們注入ContactService並調用實例的getContacts()方法(在ngOnInit生命週期事件上)來獲取聯繫人並將它們分配給contacts數組。

接下來打開src/app/contact-list/contact-list.component.html文件並添加:

 <table> <tr> <th>Name</th> <th>Email</th> <th>Actions</th> </tr> <tr *ngFor="let contact of contacts" > <td>{{ contact.name }}</td> <td>{{ contact.email }}</td> <td> <a [routerLink]="['/contact', contact.id]">Go to details</a> </td> </tr> </table>

我們遍歷聯繫人並顯示每個聯繫人的姓名和電子郵件。 我們還使用routerLink指令創建到每個聯繫人詳細信息組件的鏈接。

這是組件的屏幕截圖:

聯繫人列表
聯繫人列表(大預覽)

當我們點擊Go to details鏈接時,它會將我們帶到ContactDetailsComponent 。 路由有一個id參數,讓我們看看如何從我們的組件中訪問它。

打開src/app/contact-detail/contact-detail.component.ts文件並將代碼更改為類似於以下代碼:

 import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { ContactService } from '../contact.service'; @Component({ selector: 'app-contact-detail', templateUrl: './contact-detail.component.html', styleUrls: ['./contact-detail.component.css'] }) export class ContactDetailComponent implements OnInit { contact: any; constructor(private contactService: ContactService, private route: ActivatedRoute) { } ngOnInit() { this.route.paramMap.subscribe(params => { console.log(params.get('id')) this.contactService.getContact(params.get('id')).subscribe(c =>{ console.log(c); this.contact = c; }) }); } }

我們將ContactServiceActivatedRoute注入到組件中。 在ngOnInit()生命週期事件中,我們檢索將從路由傳遞的id參數,並使用它來獲取我們分配給contact對象的聯繫人詳細信息。

打開src/app/contact-detail/contact-detail.component.html文件並添加:

 <h1> Contact # {{contact.id}}</h1> <p> Name: {{contact.name}} </p> <p> Email: {{contact.email}} </p> 
聯繫方式
聯繫方式(大預覽)

當我們第一次從127.0.0.1:4200/訪問我們的應用程序時,outlet 不會渲染任何組件,所以讓我們通過將以下路由添加到 routes 數組來將空路徑重定向到contacts路徑:

 {path: '', pathMatch: 'full', redirectTo: 'contacts'}

我們想要匹配確切的空路徑,這就是我們指定完整匹配策略的原因。

結論

在本教程中,我們了解瞭如何使用 Angular 路由器將路由和導航添加到我們的應用程序中。 我們已經看到了不同的概念,例如路由器出口、路由和路徑,並且我們創建了一個演示來實際展示不同的概念。 您可以從此存儲庫訪問代碼。