你好!我希望您已經閱讀了我們有關 angular 組件和路由的教程。在這篇文章中,我們將繼續討論 angular 中的另一個有趣的概念:服務。
如果 Angular 組件是我們應用程序的表示層,那么什么將負責實際獲取真實數據并執行業務邏輯?這正是 Angular 服務的用武之地。Angular 服務的作用是獲取、組織并最終跨組件共享數據、模型和業務邏輯。
在深入了解 Angular 服務的技術細節之前,讓我們先了解一下其功能。這將幫助您了解代碼的哪一部分需要放置在組件內,以及哪一部分需要放置在 Angular 服務內。
以下是有關服務的一些重要事實:
服務是使用 @Injectable 裝飾器定義的。這告訴 Angular 該服務可以注入到組件或其他服務中。稍后我們將詳細討論注入服務。
服務是保存所有業務邏輯并跨組件共享的地方。這使您的應用程序更具可擴展性和可維護性。通常,服務也是與后端交互的正確位置。例如,如果您需要進行AJAX調用,可以在服務內部創建完成調用的方法。
服務是單例類。您的 Angular 應用程序中只會運行特定服務的單個實例。
什么是服務?
Angular 中的服務是在應用程序的生命周期中僅實例化一次的對象。服務接收和維護的數據可以在整個應用程序中使用。這意味著組件可以隨時從服務獲取數據。 依賴注入用于在組件內部引入服務。
讓我們嘗試了解如何創建服務并在 Angular 組件中使用它。您可以在我們的 GitHub 存儲庫中找到該項目的完整源代碼。
獲得源代碼后,導航到項目目錄并使用 npm install 安裝所需的依賴項。安裝依賴項后,通過鍵入以下命令啟動應用程序:
ng serve
您應該讓應用程序在 https://localhost:4200/. 上運行
我們項目的整體文件夾結構如下。
src --app ----components ------employee.component.css ------employee.component.html ------employee.component.ts ----services ------employee.service.spec.ts ------employee.service.ts ------employeeDetails.service.ts --app.routing.module.ts --app.component.css --app.component.html --app.component.spec.ts --app.component.ts --app.module.ts --assets --index.html --tsconfig.json
1.構建服務的骨架
在 Angular 中創建服務有兩種方法:
- 在項目內手動創建文件夾和文件。
- 使用 ng g service
命令自動創建服務。使用此方法時,您將在所選目錄中自動獲取 .service.ts 和 .service.spec.ts 文件。
ng g service components/employee
2. 創建服務
現在,.service.ts 文件已在您的項目結構中創建,是時候填充服務的內容了。為此,您必須決定服務需要做什么。請記住,您可以擁有多個服務,每個服務都執行特定的業務操作。在我們的例子中,我們將使用 employee.service.ts 將靜態角色列表返回給使用它的任何組件。
在employee.service.ts中輸入以下代碼。
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root', }) export class EmployeeService { role = [ {'id':'1', 'type':'admin'}, {'id':'2', 'type':'engineer'}, {'id':'3', 'type':'sales'}, {'id':'4', 'type':'human_resources'} ] getRole(){ return this.role; } }
此服務僅向應用程序返回角色的靜態列表。讓我們逐行解碼該服務。
- 我們從 @angular/core 庫導入 Injectable 。這一點至關重要,因為我們的服務將被使用或注入到組件中。 @Injectable 指令允許我們識別服務。
- 接下來,我們應用 @Injectable 裝飾器。 @Injectable 的 providedIn 屬性指定注入器的可用位置。大多數時候,root 被指定為它的值。這意味著可以在應用程序級別注入服務。其他選項為 any、platform、null 或 Type
。 - 我們創建一個類組件,名稱為 EmployeeService。該類有一個方法 getRole,它返回一個靜態對象數組。
3.創建組件
如前所述,Angular 中的服務用于保存應用程序的業務邏輯。為了向查看者顯示數據,我們需要一個表示層。這就是傳統的基于類的 Angular 組件的用武之地,它是使用裝飾器 @Component 創建的。
您可以在本系列的上一篇文章中了解有關 Angular 組件的更多信息。它將幫助您理解 Angular 組件并創建您自己的組件。創建文件 employee.component.ts 并向其中添加以下代碼:
import { Component, OnInit } from '@angular/core'; import { EmployeeService } from '../services/employee.service'; @Component({ selector: 'employee', templateUrl: './employee.component.html' }) export class EmployeeComponent implements OnInit { role: any; constructor(private employeeService: EmployeeService) { } ngOnInit(): void { this.role = this.employeeService.getRole() } }
讓我們分解一下:
- 導入 @Component 裝飾器并調用它。我們指定 ’employee’ 作為選擇器,并提供一個指向描述組件視圖的 HTML 的模板 URL。
- 聲明組件類并指定它實現 OnInit。因此,我們可以定義一個 ngOnInit 事件處理程序,該處理程序將在創建組件時調用。
- 為了使用我們的服務,必須在構造函數內聲明它。在我們的例子中,您將在構造函數中看到 private employeeService: EmployeeService 。通過此步驟,我們將使該服務可以跨組件訪問。
- 由于我們的目標是在創建員工組件時加載角色,因此我們在 ngOnInit 中獲取數據。
這可以變得更簡單嗎?由于該服務是一個單例類,因此可以在多個組件之間重用,而不會造成任何性能損失。
4.創建視圖
現在我們的組件中有數據了,讓我們構建一個簡單的 employee.component.html 文件來迭代角色并顯示它們。下面,我們使用 *ngFor 來迭代角色,并僅向用戶顯示類型。
<h3>Data from employee.service</h3>
- {{role.type}}
5.運行項目
在項目啟動并運行之前我們只剩下一步了。我們需要確保 employee.component.ts 文件包含在 @NgModule 指令內的聲明列表中。
如下所示,EmployeeComponent 已添加到 app.module.ts 文件中。
//app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { EmployeeComponent } from './components/employee.component'; @NgModule({ declarations: [ AppComponent, EmployeeComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
有趣的是,我們尚未將該服務添加到我們的提供商列表中,但我們能夠成功使用該服務。為什么?因為我們已經指定在應用程序的根級別提供服務(即使用 providedIn: ‘root’ 參數)。但是,請繼續閱讀以了解有關我們確實需要在 @NgModule 的 providers 數組中提及服務的場景的更多信息。
此外,我們還需要將 employee 元素添加到 app.component.html 文件中。
<h1> Tutorial: Angular Services </h1> <employee></employee><router-outlet></router-outlet>
如果我們到目前為止運行我們的應用程序,它將如下所示:
6.從服務動態獲取數據
現在,我們將獲取特定于 employee.component.ts 的數據。
讓我們創建一個新服務來從 API 獲取數據。
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable() export class EmployeDetailsService { fetchEmployeeDetailsURL = 'https://reqres.in/api/users?page=2' constructor(private http: HttpClient) { } fetchEmployeeDetails = () => { return this.http.get(this.fetchEmployeeDetailsURL); } }
現在,讓我們逐行理解我們的代碼。
- 由于我們要通過 AJAX 調用獲取數據,因此導入 HttpClient 非常重要。如果您是 HttpClient 的新手,您可以在本系列的另一篇文章中了解更多信息。
- 在我們的 EmployeeDetailsS??ervice 中,我們沒有指定 provideIn 參數。這意味著我們需要執行額外的步驟來讓整個應用程序了解我們的可注入服務。您將在下一步中了解這一點。
- HttpClient 本身就是一個可注入服務。在構造函數中聲明它,以便將其注入到組件中。在 fetchEmployeeDetails 方法中,我們將使用 HttpClient.get 方法從 URL 獲取數據。
7. 在 app.module 中注冊服務
與我們的第一個服務不同,我們在 app.module.ts 中注冊 EmployeeDetailsS??ervice 至關重要,因為我們尚未在根級別聲明可注入。這是更新后的 app.module.ts 文件:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { EmployeeComponent } from './components/employee.component'; import { EmployeDetailsService } from './services/employeeDetails.service'; @NgModule({ declarations: [ AppComponent, EmployeeComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule ], providers: [ EmployeDetailsService], bootstrap: [AppComponent] }) export class AppModule { }
如果您密切關注,您可能會注意到兩個重要的變化:
- 在我們的 app.module.ts 文件中,我們需要將 EmployeDetailsS??ervice 包含在 Providers 列表中。
- 我們需要從 @angular/common/http 導入 HttpClientModule。 HttpClientModule 必須包含在我們的 imports 列表中。
就是這樣 – 我們現在準備在組件中使用 EmployeeDetailsS??ervice 。
8.獲取動態數據
為了適應新服務,我們將對組件進行一些更改。
添加一個按鈕來加載數據
首先,我們將在視圖中添加一個按鈕。當我們單擊此按鈕時,將通過 AJAX 調用加載數據。這是更新后的employee.component.html文件:
<h3>Data from employee.service</h3>
- {{role.type}}
- {{employee.email}}
訂閱Getter函數
接下來訂閱EmployeDetailsS??ervice中的getter函數。為此,我們將 EmployeDetailsS??ervice 添加到 employee.component.ts 中的構造函數中:
import { Component, OnInit } from '@angular/core'; import { EmployeeService } from '../services/employee.service'; import { EmployeDetailsService } from '../services/employeeDetails.service'; @Component({ selector: 'employee', templateUrl: './employee.component.html' }) export class EmployeeComponent implements OnInit { roles: any; employeeDetails: any; constructor(private employeeService: EmployeeService, private employeeDetailsService: EmployeDetailsService) { } ngOnInit(): void { this.roles = this.employeeService.getRole() } loadEmployeeDetails = () => { this.employeeDetailsService.fetchEmployeeDetails() .subscribe((response:any)=>{ this.employeeDetails = response.data; }) } }
完成此更改后,單擊 LoadEmployeeDetails 按鈕,我們將看到以下視圖。
結論
給你!我們已經逐步構建了一個可以處理靜態和動態數據的 Angular 服務。現在,您應該能夠構建自己的 Angular 服務并使用它們通過 AJAX 調用獲取數據。您甚至可以以更可重用的方式實現業務邏輯。