iT邦幫忙

2021 iThome 鐵人賽

DAY 9
0
Modern Web

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

新新新手閱讀 Angular 文件 - Add Service(2) - Day09

  • 分享至 

  • xImage
  •  

學習目標

這一篇是紀錄閱讀官方文件 Add services 的筆記內容。
本篇的內容是接續 Day08 的後續內容。

Observable 型別的資料

到目前為止,我們元件中接收資料都是以同步的形式接收資料庫中的資料,但是,在實務上的運用不是用這種形式來接收資料的,而是用非同步的方式去遠端的伺服器端取得所需的資料。

所以,我們會利用 Angular 中的 HttpClient.get 的方式來達成非同步從遠端 server 取得資料的機制。

在 Angular 中的 HttpClient.get() 是會回傳一個 Observable 的結果。

加入 Observable 到 HeroService 中

所以,我們要引入一些來自 RxJS 的內容來更改一下原本的 HersoService 檔案的回傳資料型別,然後,改一下原本的 getHeroes 函式的回傳資料型別

--- hero.service.ts ---
import { HERO } from './hero';
import { HEROES } from './mock-heroes';
import { Observable, of } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class HeroService {
	// ...
  getHeroes(): Observable<HERO[]> {
    const heroes = of(HEROES);
    return heroes;
  }
}

可以看到上面的範例有寫 of(HEROES) ,它會回傳一個 Observable<HERO[]>,它會發送出一個單一值,這個值是一個英雄資料的陣列。

訂閱 HeroesComponent 的回傳資料

因為,在 HeroService 的回傳資料型別已經改成 Observable<Hero[]>,所以,我們要更改一下 HeroComponent 的 getHeroes 的內容

--- heroes.component.ts ---
getHeroes(): void {
  this.heroService.getHeroes()
      .subscribe(heroes => this.heroes = heroes);
}

加入 Observable 到我們回傳的資料格式之後,這個回傳的機制就會等待 Observable 發送出含有英雄資料的陣列,接著,才會執行 subscribe 的內容,也就是將發送出來的陣列設給 HeroComponent 的 heroes 中。

加入展示訊息的元件和服務

接下來我們要新增 MessageComponent 和 MessageService,
MessageComponent 會負責展示訊息在畫面的底部,
MessageService 會負責傳送要被呈現的訊息內容

新增 MessagesComponent 元件 和 MessageService

輸入 ng generate component messages ,新增這個元件之後,再把它加入到 app.component.html。
接著,輸入 ng generate service message 來新增這個服務,然後,在它的檔案內容加入以下的內容,內容就是把 cache 住的訊息內容加入其他內容或者清除這個 cache 的內容。

--- message.service.ts ---
@Injectable({
  providedIn: 'root',
})
export class MessageService {
  messages: string[] = [];
  add(message: string) {
    this.messages.push(message);
  }
  clear() {
    this.messages = [];
  }
}

接下來,我們把 MessageService 注入到 HeroService 中,
並且將 MessageService 的加入訊息內容的功能,加到 getHeroes 中

--- hero.service.ts ---
import { MessageService } from './message.service';

export class HeroService {
  constructor(private messageService:MessageService) { }

	getHeroes(): Observable<HERO[]> {
	    const heroes = of(HEROES);
	    this.messageService.add('HeroService: fetched heroes');  // 加入MessageService服務
	    return heroes;
	  }
}

在 HeroService 加入 message 的功能

因為 MessagesComponent 元件是負責將 cache 的訊息呈現出來,所以,也要將 MessageService 的內容引入這個元件中

--- messages.component.ts ---
import { MessageService } from '../message.service';
@Component({
	// ...
})
export class MessagesComponent implements OnInit {
  constructor(public messageService:MessageService) { }
}

Note:
這邊要注意一下,我們在建構式將 messageService 設為 public 成員,因為,未來它會被樣板中的元素做連結,若用 private 來宣告它的話,就沒有辦法在樣板中調用它。
Angular 只有連結 public 的元件屬性

繫結 MessageService

接下來就把 MessageService 的內容加到 MessagesComponent 的樣板中吧~

--- messages.component.html ---
<div *ngIf="messageService.messages.length">
  <h2>Messages</h2>
  <button class="clear"
          (click)="messageService.clear()">Clear messages</button>
  <div *ngFor='let message of messageService.messages'> {{message}} </div>
</div>

這邊可以注意到一點,有特別加了 *ngIf 的判定,來防止當 messageService.messages 沒有任何內容的時候,瀏覽器會報錯。

將 MessageService 功能注入到 HeroService 中

接下來,我們也要將 messageService 加入到 HeroComponent 中,讓當有英雄被點擊後,被點選的英雄資訊會出現在 messageService 的提示訊息中。

import { MessageService } from '../message.service';

@Component({
  // ...
})
export class HeroesComponent implements OnInit {
	// ...
  constructor(private heroService: HeroService, private messageService: MessageService) { }
  onSelect(hero: Hero): void {
    this.selectedHero = hero;
    this.messageService.add(`HeroesComponent: Selected hero id=${hero.id}`);
  }
}

最後成果

完成以上的內容之後,就可以看到以下的操作動畫成果囉~

Summary

這邊做個總結

  1. 我們加入了 RxJS 的 Observable 和 of 來完成非同步的資料接收的機制。
  2. 加入了 MessageService 和 MessageComponent 來達成傳遞訊息和展示訊息的功能。

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

尚未有邦友留言

立即登入留言