這篇文章我們來講解如何使用 service(服務) Angular
,談及服務我們就要了解什麼是服務;在
中,我們所說的服務是指那些能夠被其它的元件或者指令調用的單一的,可共享的代碼塊.服務能夠使我們提高代碼的使用率,友善元件之間共享資料和方法,友善測試和維護.
如果你看了上一篇文章
Step 5 - Dependency Injection,你就會發現我們這一部分講解的内容和上一篇有很多的相似之處;當然也有一些新的知識點,溫故而知新嘛;好了讓我們來開始今天的旅行吧.
首先我們還是切換回之前的
quickstart 版本,然後運作:npm run start
可以看到
My First Angular2 Travel
,然後繼續我們的鋪墊工作;主要是三個部分:
1.将我們的元件模闆使用單一的
html
模闆來替代;
2.建構
User
類友善我們後面的使用;
3.建構我們的模拟資料,友善我們使用服務來擷取這些資料;
首先我們來完成第一部分,修改
app.component.ts
中
@Component
的中繼資料:
template: '
My First Angular2 Travel
My First Angular2 Travel
'
改為:
templateUrl: 'app/templates/main.html'
,然後我們在
main.html
中書寫我們的模闆代碼:
My First Angular2 Travel
然後我們來進行第二個工作,建立我們的
User
類;為了展示友善,我們就給
User
兩個屬性吧,一個是
id(number)
,一個是
name(string)
;檔案的路徑是:
app/classes/User.ts
,具體的代碼如下:
export class User {
constructor(
private id: number,
private name: string
){}
上面注釋的部分是這個
User
類的簡寫,這個根據個人的喜好;你喜歡寫就怎麼寫.
最後一項工作就是來創造我們的模拟資料,我們現在還沒有學習如何在
Angular2
中使用
HTTP
,是以我們暫時将這些資料記錄在一個檔案中,然後導出這些資料,供我們接下來使用.我們的模拟資料檔案路徑是:
app/mock/user.data.ts
;下面是代碼部分:
import {User} from "../classes/User";
export const USERS: User[] = [
{id: 1, name: 'dreamapple1'},
{id: 2, name: 'dreamapple2'},
{id: 3, name: 'dreamapple3'},
{id: 4, name: 'dreamapple4'},
{id: 5, name: 'dreamapple5'},
{id: 6, name: 'dreamapple6'},
{id: 7, name: 'dreamapple7'},
{id: 8, name: 'dreamapple8'}
可以看到,我們導出了一個數組,這個數組的每一個元素都是一個
User
類的執行個體.
接下來,我們就要步入今天的主題了;建構一個服務,這個服務能夠擷取我們剛剛書寫的模拟資料;首先不要忘記的是,
service
是一個類,然後這個類可以注入到别的元件
或者指令中去,還有一點就是我們知道,擷取資料的服務往往都是異步的,是以我們使用了
Promise
去封裝我們擷取到的資料,來模拟異步請求;檔案的路徑是:
app/service/user.service.ts
,我們也遵循一個約定,服務的檔案字尾是
*.service.ts
,前面的單詞如果是多個的話就使用短橫線來連接配接,比如
SpecialUserService
我們就寫成
special-user.service.ts
,詳細的部分請看代碼:
import {User} from "../classes/User";
import {USERS} from "../mock/user.data";
export class UserService {
getUsers(): User[] {
return Promise.resolve(USERS);
關于上面代碼的一些解釋:因為我們的
getUsers
函數是有傳回值的,它的傳回值是一個數組,數組的每一個元素都是
User
類的執行個體,是以我們使用了
getUsers(): User[]
,還有因為我們要模拟異步請求擷取資料,是以我們使用了
Promise
,如果你對
Promise
有什麼不懂的地方,可以看看
這裡.
接下來我們就要使用這個服務了,如何使用這個服務呢?在上一章節中我們已經講解了許多種使用服務的方法;現在我們使用最簡單的一種方式,直接使用
providers
來注入我們的服務,然後我們還要把我們擷取到的資料展示到我們的模闆中,具體的代碼如下所示:
import {Component} from '@angular/core';
import {User} from "./classes/User";
import {UserService} from "./services/user.service";
* 别忘記了使用@字首
* 這裡相當于元件視圖
@Component({
selector: 'my-app',
templateUrl: 'app/templates/main.html',
providers: [UserService]
* 導出這個元件,也就是一個類
* 這裡相當于元件控制器
export class AppComponent {
users: User[];
constructor(private userService: UserService){
this.userService.getUsers().then(
users => this.users = users
我們也要改動
main.html
的内容:
My First Angular2 Travel
{{user.name}}
這時我們打開浏覽器,就會看到我們想要的結果:

上面的寫法是有一些問題的,構造函數是為了簡單的初始化工作而設計的,比如把構造函數的參數指派給屬性.它的負擔不應該過于沉重.是以我們把資料的擷取放在了元件的生命周期的鈎子函數中去,如果你不了解元件的生命周期的話,那麼你可以
看看這裡,在這裡我們使用了
ngOnInit
;我們修改一下上面的代碼:
import {Component, OnInit} from '@angular/core';
import {User} from "./classes/User";
import {UserService} from "./services/user.service";
/*
* 别忘記了使用@字首
* 這裡相當于元件視圖
*/
@Component({
selector: 'my-app',
//template: '
My First Angular2 Travel
',
templateUrl: 'app/templates/main.html',
providers: [UserService]
})
/*
* 導出這個元件,也就是一個類
* 這裡相當于元件控制器
*/
export class AppComponent implements OnInit{
users: User[];
constructor(
private userService: UserService
){}
getUsersData() {
this.userService.getUsers()
.then(users => this.users = users);
}
ngOnInit() {
this.getUsersData();
}
}
上面代碼的一些解釋,首先我們在
@angular/core
中導出了
OnInit
這個接口,然後我們又通過元件中的
ngOnInit
方法實作了這個接口;将構造函數中的擷取資料的業務提取了出來,這種做法是元件初始化的時候擷取資料比較好的一種方案.我們在後面的文章中也會講解關于元件或者指令生命周期的文章.
最後,我們還可以更真實的的去模拟從伺服器讀取資料的操作;我們可以通過使用
setTimeout
來延時擷取我們的資料,這就很好地模拟了我們從伺服器擷取資料的操作;具體的代碼部分看下面:
import {User} from "../classes/User";
import {USERS} from "../mock/user.data";
export class UserService {
getUsers(): Promise {
return Promise.resolve(USERS);
getMockUsers(): Promise {
return new Promise(resolve => setTimeout(resolve(USERS), 2000))
.then(() => this.getUsers());
首先需要注意的一點是,我們之前寫的代碼把
getUsers()
函數的傳回值定義為
User[]
,其實更準确的應該是
Promise[]>
;我們接下來寫的函數
getMockUsers()
利用
setTimeout
延時傳回了我們的模拟資料.
其實我們的程式裡還有一個小錯誤,不容易被發現;當我在建構的時候我發現了下面的錯誤:
它提醒我們說,
Property 'id' is private in type 'User' but not in type '{ id: number; name: string; }'.
這是因為我們把
id
作為
User
的私有屬性了,但是在
{ id: number; name: string; }
對象中,
id
不是私有的屬性;要解決這個問題有多種思路,你可以将我們的模拟資料使用
User
類來建立,或者将
id
和
name
public
屬性.那我們就取一個簡單的方法,将屬性定義為
public
User
類的代碼修改如下:
export class User {
id: number;
name: string;
//constructor(
// private id: number,
// private name: string
//){}
}
在TypeScript裡,每個成員預設為是public的.是以上面的寫法是很簡便的.
到這裡我們要說的内容已經說完了,源代碼可以參考這裡
angular2-travel,當然歡迎
批評指正原文釋出時間為:2016年09月20日
原文作者:掘金
本文來源:
掘金如需轉載請聯系原作者