本教學課程示範如何建立 Angular 服務,並使用依賴注入將它納入你的應用程式。
你將學到什麼
你的應用程式將會有一個服務,它會讀取本機的靜態資料並提供給你的應用程式。 在之後的課程中,你會更新這個服務,讓它從網路服務取得資料。
服務概念預覽
本教學介紹 Angular 服務與依賴注入。
Angular 服務
_Angular 服務_提供了一種方式,讓你將應用程式的資料與功能分離出來,供應用程式中的多個元件使用。 一個服務要能被多個元件使用,必須先做成可注入的(injectable)。 可注入且被元件使用的服務,會成為該元件的相依性。 元件依賴這些服務,沒有它們就無法運作。
依賴注入
_依賴注入_是管理應用程式元件相依性,以及其他元件可使用之服務的機制。
-
為你的應用程式建立新服務
這個步驟會為你的應用程式建立一個可注入的服務。
在 IDE 的 Terminal 窗格中:
在你的專案目錄中,進入
first-app目錄。在
first-app目錄中,執行下列指令,建立新服務。ng generate service housingService --skip-tests執行
ng serve,建置應用程式並將它提供到http://localhost:4200。確認應用程式建置時沒有錯誤。 繼續下一步之前,請先修正任何錯誤。
-
將靜態資料加入新服務
這個步驟會為你的新服務加入一些範例資料。 在之後的課程中,你會將靜態資料換成網路介面,像在真正的應用程式中一樣取得資料。 目前,你的應用程式的新服務使用的是到目前為止在本機
Home中建立的資料。在 IDE 的 Edit 窗格中:
在
src/app/home/home.ts中,從Home複製baseUrl變數與housingLocationList變數及其陣列值。在
src/app/housing-service.ts中:在
HousingService類別內,貼上你在上一個步驟中從Home複製的變數。在
HousingService類別內,將這些函式貼在你剛複製的資料之後。 這些函式讓相依者能存取服務的資料。src/app/housing-service.ts 中的服務函式
import {Service} from '@angular/core'; import {HousingLocationInfo} from './housinglocation'; @Service() export class HousingService { readonly baseUrl = 'https://angular.dev/assets/images/tutorials/common'; protected housingLocationList: HousingLocationInfo[] = [ { id: 0, name: 'Acme Fresh Start Housing', city: 'Chicago', state: 'IL', photo: `${this.baseUrl}/bernard-hermant-CLKGGwIBTaY-unsplash.jpg`, availableUnits: 4, wifi: true, laundry: true, }, { id: 1, name: 'A113 Transitional Housing', city: 'Santa Monica', state: 'CA', photo: `${this.baseUrl}/brandon-griggs-wR11KBaB86U-unsplash.jpg`, availableUnits: 0, wifi: false, laundry: true, }, { id: 2, name: 'Warm Beds Housing Support', city: 'Juneau', state: 'AK', photo: `${this.baseUrl}/i-do-nothing-but-love-lAyXdl1-Wmc-unsplash.jpg`, availableUnits: 1, wifi: false, laundry: false, }, { id: 3, name: 'Homesteady Housing', city: 'Chicago', state: 'IL', photo: `${this.baseUrl}/ian-macdonald-W8z6aiwfi1E-unsplash.jpg`, availableUnits: 1, wifi: true, laundry: false, }, { id: 4, name: 'Happy Homes Group', city: 'Gary', state: 'IN', photo: `${this.baseUrl}/krzysztof-hepner-978RAXoXnH4-unsplash.jpg`, availableUnits: 1, wifi: true, laundry: false, }, { id: 5, name: 'Hopeful Apartment Group', city: 'Oakland', state: 'CA', photo: `${this.baseUrl}/r-architecture-JvQ0Q5IkeMM-unsplash.jpg`, availableUnits: 2, wifi: true, laundry: true, }, { id: 6, name: 'Seriously Safe Towns', city: 'Oakland', state: 'CA', photo: `${this.baseUrl}/phil-hearing-IYfp2Ixe9nM-unsplash.jpg`, availableUnits: 5, wifi: true, laundry: true, }, { id: 7, name: 'Hopeful Housing Solutions', city: 'Oakland', state: 'CA', photo: `${this.baseUrl}/r-architecture-GGupkreKwxA-unsplash.jpg`, availableUnits: 2, wifi: true, laundry: true, }, { id: 8, name: 'Seriously Safe Towns', city: 'Oakland', state: 'CA', photo: `${this.baseUrl}/saru-robert-9rP3mxf8qWI-unsplash.jpg`, availableUnits: 10, wifi: false, laundry: false, }, { id: 9, name: 'Capital Safe Towns', city: 'Portland', state: 'OR', photo: `${this.baseUrl}/webaliser-_TPTXZd9mOo-unsplash.jpg`, availableUnits: 6, wifi: true, laundry: true, }, ]; getAllHousingLocations(): HousingLocationInfo[] { return this.housingLocationList; } getHousingLocationById(id: number): HousingLocationInfo | undefined { return this.housingLocationList.find((housingLocation) => housingLocation.id === id); } }之後的課程會用到這些函式。目前只要理解這些函式會依 id 回傳特定的
HousingLocation,或回傳整份清單即可。為
HousingLocation加入檔案層級的匯入。在 src/app/housing-service.ts 中匯入 HousingLocation 型別
import {Service} from '@angular/core'; import {HousingLocationInfo} from './housinglocation'; @Service() export class HousingService { readonly baseUrl = 'https://angular.dev/assets/images/tutorials/common'; protected housingLocationList: HousingLocationInfo[] = [ { id: 0, name: 'Acme Fresh Start Housing', city: 'Chicago', state: 'IL', photo: `${this.baseUrl}/bernard-hermant-CLKGGwIBTaY-unsplash.jpg`, availableUnits: 4, wifi: true, laundry: true, }, { id: 1, name: 'A113 Transitional Housing', city: 'Santa Monica', state: 'CA', photo: `${this.baseUrl}/brandon-griggs-wR11KBaB86U-unsplash.jpg`, availableUnits: 0, wifi: false, laundry: true, }, { id: 2, name: 'Warm Beds Housing Support', city: 'Juneau', state: 'AK', photo: `${this.baseUrl}/i-do-nothing-but-love-lAyXdl1-Wmc-unsplash.jpg`, availableUnits: 1, wifi: false, laundry: false, }, { id: 3, name: 'Homesteady Housing', city: 'Chicago', state: 'IL', photo: `${this.baseUrl}/ian-macdonald-W8z6aiwfi1E-unsplash.jpg`, availableUnits: 1, wifi: true, laundry: false, }, { id: 4, name: 'Happy Homes Group', city: 'Gary', state: 'IN', photo: `${this.baseUrl}/krzysztof-hepner-978RAXoXnH4-unsplash.jpg`, availableUnits: 1, wifi: true, laundry: false, }, { id: 5, name: 'Hopeful Apartment Group', city: 'Oakland', state: 'CA', photo: `${this.baseUrl}/r-architecture-JvQ0Q5IkeMM-unsplash.jpg`, availableUnits: 2, wifi: true, laundry: true, }, { id: 6, name: 'Seriously Safe Towns', city: 'Oakland', state: 'CA', photo: `${this.baseUrl}/phil-hearing-IYfp2Ixe9nM-unsplash.jpg`, availableUnits: 5, wifi: true, laundry: true, }, { id: 7, name: 'Hopeful Housing Solutions', city: 'Oakland', state: 'CA', photo: `${this.baseUrl}/r-architecture-GGupkreKwxA-unsplash.jpg`, availableUnits: 2, wifi: true, laundry: true, }, { id: 8, name: 'Seriously Safe Towns', city: 'Oakland', state: 'CA', photo: `${this.baseUrl}/saru-robert-9rP3mxf8qWI-unsplash.jpg`, availableUnits: 10, wifi: false, laundry: false, }, { id: 9, name: 'Capital Safe Towns', city: 'Portland', state: 'OR', photo: `${this.baseUrl}/webaliser-_TPTXZd9mOo-unsplash.jpg`, availableUnits: 6, wifi: true, laundry: true, }, ]; getAllHousingLocations(): HousingLocationInfo[] { return this.housingLocationList; } getHousingLocationById(id: number): HousingLocationInfo | undefined { return this.housingLocationList.find((housingLocation) => housingLocation.id === id); } }
確認應用程式建置時沒有錯誤。 繼續下一步之前,請先修正任何錯誤。
-
將新服務注入
Home這個步驟會將新服務注入應用程式的
Home,讓它能從服務讀取應用程式的資料。 在之後的課程中,你會將靜態資料換成即時資料來源,像在真正的應用程式中一樣取得資料。在 IDE 的 Edit 窗格中,在
src/app/home/home.ts裡:在
src/app/home/home.ts頂部,將inject加入從@angular/core匯入的項目中。這會將inject函式匯入Home類別。更新 src/app/home/home.ts
import {Component, inject} from '@angular/core'; import {HousingLocation} from '../housing-location/housing-location'; import {HousingLocationInfo} from '../housinglocation'; import {HousingService} from '../housing-service'; @Component({ selector: 'app-home', imports: [HousingLocation], template: ` <section> <form> <input type="text" placeholder="Filter by city" /> <button class="primary" type="button">Search</button> </form> </section> <section class="results"> @for (housingLocation of housingLocationList; track $index) { <app-housing-location [housingLocation]="housingLocation" /> } </section> `, styleUrl: './home.css', }) export class Home { housingLocationList: HousingLocationInfo[] = []; housingService: HousingService = inject(HousingService); constructor() { this.housingLocationList = this.housingService.getAllHousingLocations(); } }為
HousingService加入新的檔案層級匯入:在 src/app/home/home.ts 中加入匯入
import {Component, inject} from '@angular/core'; import {HousingLocation} from '../housing-location/housing-location'; import {HousingLocationInfo} from '../housinglocation'; import {HousingService} from '../housing-service'; @Component({ selector: 'app-home', imports: [HousingLocation], template: ` <section> <form> <input type="text" placeholder="Filter by city" /> <button class="primary" type="button">Search</button> </form> </section> <section class="results"> @for (housingLocation of housingLocationList; track $index) { <app-housing-location [housingLocation]="housingLocation" /> } </section> `, styleUrl: './home.css', }) export class Home { housingLocationList: HousingLocationInfo[] = []; housingService: HousingService = inject(HousingService); constructor() { this.housingLocationList = this.housingService.getAllHousingLocations(); } }從
Home中刪除baseUrl變數,刪除housingLocationList陣列的項目,並將housingLocationList指派為空陣列([])。再過幾個步驟,你會更新程式碼,讓它從HousingService拉取資料。在
Home中,加入下列程式碼,注入新服務並為應用程式初始化資料。constructor是這個元件建立時第一個執行的函式。constructor中的程式碼會將housingLocationList指派為呼叫getAllHousingLocations所回傳的值。在 src/app/home/home.ts 中從服務初始化資料
import {Component, inject} from '@angular/core'; import {HousingLocation} from '../housing-location/housing-location'; import {HousingLocationInfo} from '../housinglocation'; import {HousingService} from '../housing-service'; @Component({ selector: 'app-home', imports: [HousingLocation], template: ` <section> <form> <input type="text" placeholder="Filter by city" /> <button class="primary" type="button">Search</button> </form> </section> <section class="results"> @for (housingLocation of housingLocationList; track $index) { <app-housing-location [housingLocation]="housingLocation" /> } </section> `, styleUrl: './home.css', }) export class Home { housingLocationList: HousingLocationInfo[] = []; housingService: HousingService = inject(HousingService); constructor() { this.housingLocationList = this.housingService.getAllHousingLocations(); } }儲存對
src/app/home/home.ts的變更,確認你的應用程式建置時沒有錯誤。 繼續下一步之前,請先修正任何錯誤。
SUMMARY: 在這一課中,你為應用程式加入了一個 Angular 服務,並將它注入 Home 類別。
這讓應用程式取得資料的方式有了清楚的區隔。
目前,新服務是從靜態資料陣列取得資料。
在之後的課程中,你會重構這個服務,讓它從 API 端點取得資料。
如需本課所涵蓋主題的更多資訊,請造訪: