天天看點

掌握 Angular2 的服務 (service)My First Angular2 TravelMy First Angular2 Travel

這篇文章我們來講解如何使用

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

'

改為:

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}}
           

這時我們打開浏覽器,就會看到我們想要的結果:

掌握 Angular2 的服務 (service)My First Angular2 TravelMy First Angular2 Travel

上面的寫法是有一些問題的,構造函數是為了簡單的初始化工作而設計的,比如把構造函數的參數指派給屬性.它的負擔不應該過于沉重.是以我們把資料的擷取放在了元件的生命周期的鈎子函數中去,如果你不了解元件的生命周期的話,那麼你可以

看看這裡

,在這裡我們使用了

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日

原文作者:掘金

本文來源: 

掘金 

如需轉載請聯系原作者

繼續閱讀