掌握Angular2的服务(service)
原文鏈接:hacking-with-angular
這篇文章我們來講解如何使用service(服務),談及服務我們就要了解什么是服務;在Angular中,我們所說的服務是指那些能夠被其它的組件或者指令調用的單一的,可共享的代碼塊.服務能夠使我們提高代碼的利用率,方便組件之間共享數據和方法,方便測試和維護.
如果你看了上一篇文章Step 5 - Dependency Injection,你就會發現我們這一部分講解的內容和上一篇有很多的相似之處;當然也有一些新的知識點,溫故而知新嘛;好了讓我們來開始今天的旅行吧.
首先我們還是切換回之前的quickstart版本,然后運行:
npm run start可以看到My First Angular2 Travel,然后繼續我們的鋪墊工作;主要是三個部分:
1.將我們的組件模板使用單一的html模板來替代;
2.構建User類方便我們后面的使用;
3.構建我們的模擬數據,方便我們使用服務來獲取這些數據;
首先我們來完成第一部分,修改app.component.ts中@Component的元數據:template: '<h1>My First Angular2 Travel</h1>'改為:templateUrl: 'app/templates/main.html',然后我們在main.html中書寫我們的模板代碼:
<h1>My First Angular2 Travel</h1>然后我們來進行第二個工作,創建我們的User類;為了展示方便,我們就給User兩個屬性吧,一個是id(number),一個是name(string);文件的路徑是:app/classes/User.ts,具體的代碼如下:
export class User {//id: number;//name: string;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,詳細的部分請看代碼:
關于上面代碼的一些解釋:因為我們的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',//template: '<h1>My First Angular2 Travel</h1>',templateUrl: 'app/templates/main.html',providers: [UserService] })/** 導出這個組件,也就是一個類* 這里相當于組件控制器*/ export class AppComponent {users: User[];constructor(private userService: UserService){//noinspection TypeScriptUnresolvedFunctionthis.userService.getUsers().then(users => this.users = users)} }我們也要改動main.html的內容:
<h1>My First Angular2 Travel</h1> <ul><li *ngFor="let user of users">{{user.name}}</li> </ul>這時我們打開瀏覽器,就會看到我們想要的結果:
上面的寫法是有一些問題的,構造函數是為了簡單的初始化工作而設計的,比如把構造函數的參數賦值給屬性.它的負擔不應該過于沉重.所以我們把數據的獲取放在了組件的生命周期的鉤子函數中去,如果你不了解組件的生命周期的話,那么你可以看看這里,在這里我們使用了ngOnInit;我們修改一下上面的代碼:
import {Component, OnInit} from '@angular/core'; import {User} from "./classes/User"; import {UserService} from "./services/user.service";/** 別忘記了使用@前綴* 這里相當于組件視圖*/ @Component({selector: 'my-app',//template: '<h1>My First Angular2 Travel</h1>',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<User[]> {return Promise.resolve(USERS);}getMockUsers(): Promise<User[]> {return new Promise(resolve => setTimeout(resolve(USERS), 2000)).then(() => this.getUsers());} }首先需要注意的一點是,我們之前寫的代碼把getUsers()函數的返回值定義為User[],其實更準確的應該是Promise<User[]>;我們接下來寫的函數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,當然歡迎批評指正.
總結
以上是生活随笔為你收集整理的掌握Angular2的服务(service)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mybatis3.4.x技术内幕(二十二
- 下一篇: phoenix 开发API系列 目录