iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
Modern Web

新新新手閱讀 Angular 文件30天系列 第 7

新新新手閱讀 Angular 文件 - Day07

  • 分享至 

  • xImage
  •  

學習目標

本文章將會是閱讀官方文件Add navigation with routing 內容所做的筆記。
接續 Day06 的內容。

新增導轉路由連結按鈕 - routerLink

在昨天的內容中,我們是透過修改網頁的路由路徑來切換網頁的內容。
但是,我們不可能讓使用者需要藉由這樣的操作,才能看到他想要看到的內容阿。
所以,Angular 提供了 navigation link 類似連結按鈕的功能,讓使用者點擊該連結按鈕之後,網頁就可以被導轉到的他們想要看到的網頁囉。

那我們就在 app.component.html 加入這個導轉的連結按鈕。

<div>
  <h1>
    {{ title }}
  </h1>
  <nav>
    <a routerLink="/heroes">Hero</a>
  </nav>
  <router-outlet></router-outlet> 
</div>

可以看到 Angular 的導轉連結按鈕是直接用 a 連結做成的,不像 Vue 是特別自製了一個 router-link 的連結按鈕。
在這個 a 連結要附上 routerLink 這個 directive 並將我們在 routing 檔案中設定的 HeroesComponent 的路由路徑 /heroes 設給它,設定完成後,你就可以在畫面中看到出現了一個 Hero 的連結按鈕。

按下去之後,可以看到網頁的 url 被加入了 hero之外 ,畫面中也出現 HeroesComponent 元件的內容囉。

新增 dashboard 元件

接下來我們要新增 dashboard 的元件,
所以,先輸入指令 ng g c dashboard ,成功創完之後,Angular CLI 會自動幫我們將這個新增的元件引入專案中。
接著,我們要為這個元件設定專屬它的路由

--- app-routing.module.ts ---
import { DashboardComponent } from './dashboard/dashboard.component';
const routes: Routes = [
  { path: 'heroes', component: HeroesComponent },
  { path: 'dashboard', component: DashboardComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

新增預設路由

dashboard 這個元件的內容,是這個專案的首頁,所以,當使用者一進入我們的網頁的時候,第一個畫面會先看到首頁的內容,這個效果就需要設定預設路由來達到囉~

--- app-routing.module.ts ---
import { DashboardComponent } from './dashboard/dashboard.component';
const routes: Routes = [
  { path: 'heroes', component: HeroesComponent },
  { path: 'dashboard', component: DashboardComponent },
  { path: '', redirectTo: '/dashboard', pathMatch: 'full'}
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

加入的程式碼內容的功能為當當下 url 為空白時,網頁路由會被導轉到 /dashboard,並且路徑的內容要完全符合空白(pathMatch: 'full'),才會執行這個導轉的功能,而當使用者一進入到網頁的時候,通常 url 會是空白的,所以,會直接被導轉到 dashboard 頁面囉。

新增導轉到 dashboard 的導轉連結按鈕

接著,在 app.component.html 檔案中加入可以將當前頁面導轉到 dashboard 頁面的連結按鈕。

--- app.component.html ---
<div>
  <h1>
    {{ title }}
  </h1>
  <nav>
    <a routerLink="/heroes">Hero</a>
    <a routerLink="/dashboard">DashBoard</a>
  </nav>
  <router-outlet></router-outlet> 
</div>

頁面導轉到呈現指定英雄資料的頁面

接下來,我們要透過改變路由,進入到指定路由,進而讓畫面呈現指定英雄的詳細資料。
所以,接下來我們就要來設定路由了
首先,我們先將 HeroesComponent 元件裡面的 app-hero-detail 標籤拿掉,免得會重複出現英雄詳細內容。

第二,到 routing 設定的檔案中,加入以下設定

--- app.routing.module.ts ---
const routes: Routes = [
  // ..
  { path: 'detail/:id', component: HeroDetailComponent }, // 呈現詳細資料的路由設定
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

可以看到路由中有一個 :id 可以用來動態設定路由,當我們點擊不一樣的英雄會傳入不一樣的 id 並獲取相對應的資料。

接下來,我們要分別在 dashboard 頁面和 HeroesComponent 頁面中英雄按鈕的 routerLink 路由設定對應路由

--- dashboard.component.html --- 
<div class="heroes-menu">
  <a *ngFor="let hero of heroes" routerLink="/detail/{{ hero.id }}">
    {{ hero.name }}
  </a>
</div>
--- heroes.component.html --- 
<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
    <a routerLink="/detail/{{hero.id}}">
      <span class="badge">{{hero.id}}</span> {{hero.name}}
    </a>
  </li>
</ul>

可被導轉到的 HeroDetailComponent

因為,現在英雄的詳細資料呈現的功能全權交給 hero-detail 元件來呈現,所以,我們必須為 hero-detail 元件做一個能夠接受傳入的英雄 id 是多少並透過這個 id 來跟資料庫要對應的英雄資料,最後,再將獲取到的資料渲染到畫面中。

首先,我們要引入以下三個模組到 hero-detail 元件中

--- hero-detail.component.ts ---
import { ActivatedRoute } from '@angular/router';
import { Location } from '@angular/common';
import { HeroService } from '../hero.service';

@Component({
  // ...
})
export class HeroDetailComponent implements OnInit {
  constructor(
    private route: ActivatedRoute,
    private heroService: HeroService,
    private location: Location
  ) { }
}

ActivatedRoute 模組,元件可以透過這個模組來獲取當下的路由資訊,所以,我們可以藉由它來取出在 url 中,該英雄的 id

HeroService 模組,模仿遠端資料庫,我們會將從 url 中取出來的 id 丟到這個模組中,接著,這個模組就會回傳相對的英雄資訊給我們。

location 模組: 用來操作瀏覽器的模組,像是前一頁、後一頁...等等,之類的功能。

從路由路徑中解析出傳入的英雄 ID

接下來,我們要從 route 中取出 id 資訊。

--- hero-detail.component.ts ---
@Component({
  // ...
})
export class HeroDetailComponent implements OnInit {
	ngOnInit(): void {
    this.getHero();
  }

  getHero(): void {
    const id = Number(this.route.snapshot.paramMap.get('id'));
    this.heroService.getHero(id)
      .subscribe(hero => this.hero = hero);
  }
}

在 ngOnInit 加入 getHero 的內容,可以在當 hero-detail 元件在創建的時候,就執行取得 url 的 id 資訊。

route.snapshot: 會在元件被創建的時候,紀錄該元件當下的 route 資訊

paramMap: 會去紀錄的 route 中取得我們在後面指定的參數內容,像這邊我們就指定要取得 id 參數的內容

最後,取到 id 的資訊之後,就把它丟到 getHero 函式中去得到相對應的英雄資訊,並將其設給 hero-detail 元件的 hero 成員。

設計回到上一頁的功能

設計一個回到上一頁的按鈕在 hero-detail 元件中。

--- hero-detail.component.html ---
<button (click)="goBack">go back</button>

--- hero-detail.component.ts---
goBack(): void {
  this.location.back();
}

這邊的內容就可以看到我們透過引入的 location 模組來達到類似像 JS 的 go.back() 讓瀏覽器回上一頁的功能。

Summary

這邊做個總結

  1. 我們可以設計像是 detail/:id 這種路由路徑,來動態切換不同的 id 對應到不同的頁面內容。
  2. 如何設定預設的首頁內容,我們可以透過 redirectTo 來達到。
  3. 如何透過 this.route.snapshot 得到當下元件的路由資訊,再透過 paramMap.get('id') 來取得路由資訊中指定的 id 參數的內容,最後,再將 id 丟到指定函式中,去資料庫取得相對應的內容,再將該內容渲染到頁面上。
  4. 利用 location 模組來達到回到上一頁的功能。

上一篇
新新新手閱讀 Angular 文件 - Day06
下一篇
新新新手閱讀 Angular 文件 - Add Services - Day08
系列文
新新新手閱讀 Angular 文件30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言