引言: 若是說組件系統(Component)是ng2應用的軀體,那把服務(Service)認爲是流通於組件之間併爲其帶來生機的血液再合適不過了。組件間通訊的其中一種優等選擇就是使用服務,在ng1裏就有了普遍使用,而ng2保持了服務的所有特性,包括其全局單例與依賴注入。今天就來實踐一下ng2的服務(Service)這一利器,來實現一個簡單的音樂播放器,重點在於使用服務來進行音頻的播放控制與全局範圍的調用。git
1、基本項目準備:github
考慮到音頻播放是個比較通用的服務,決定將其建立爲一個單獨的模塊AudioModule,而且在裏面新增音頻服務主文件audio.service.ts,通用的音頻控制中心組件audio-studio.component.ts,做爲輔助的TS接口文件play-data.model.ts與audio.model.ts。數組
最終項目音頻部分的目錄結構如圖所示:網絡
2、建立服務:angular2
ng2的服務,照官網的說法來解釋,其實只是個帶有Injectable裝飾器的類而已,沒有其餘任何特殊的定義,因此很是簡單,不過定義如此簡單的服務卻能夠完成很是多酷炫的功能。ide
在TypeScript下定義變量有了public與private的訪問級區分,因此定義服務一般套路就是,定義服務內使用的私有變量,在constructor構造函數中進行初始化操做,定義共有方法給服務的消費者使用。函數
專一於音頻播放服務的場景,咱們須要的私有變量有:this
1.音頻對象
用於經過JS進行H5音頻的播放控制
2.播放列表數據
服務內部使用的播放列表概念,實際播放音頻時都是今後列表中播放音頻,服務的消費者能夠調用接口來操做此列表
3.正在播放音頻的參數
音頻時長,當前進度以及播放模式(隨機播放之類)等
4.播放時的輪詢監聽變量
用於音頻播放過程當中自動啓動輪詢,定時(每秒)更新播放參數,當音頻暫停或中止時取消此監聽
服務初始化時須要作的事情有:3d
1.建立音頻對象
可直接使用document.createElement('audio'),但不須要將其添加到DOM中。
後續的播放控制均使用此對象來操做。
2.初始化私有變量
私有變量中播放列表是一個數組,成員的參數使用audio.model.ts來規範化,
必須包含一個Url參數存放播放源,以及其餘可選參數
相同的播放參數也用一個play-data.model.ts來規範化
3.給音頻添加onplay、onpause、onend等播放事件的監聽
此服務提供的公有接口包括:component
1. Toggle(audio)
判斷傳入的音頻是否已在列表中,已存在則播放或暫停,若不存在則添加進來並播放
2. Add()
僅添加音頻到列表中
3. Remove() 移除音頻出播放列表,須要考慮好移除後對播放隊列的影響,好比是不是正在播放的音頻被移除等等
4. Next()
5. Prev()
上一曲與下一曲操做,須要考慮到播放模式
6. Skip()
進行播放進度的跳轉
7. PlayList() 8. PlayData()
用於暴露服務所維護的兩個數據(播放列表與播放參數),在指令中都是經過這兩個接口來呈現數據的
服務的完整代碼以下:
3、使用服務:
接下來要使用服務了,再ng2中服務也要依賴具體的模塊,咱們得音頻服務依賴的就是本身的音頻模塊,在模塊的provider列表中配置它:
@NgModule({ imports: [ CommonModule, SharedModule ], declarations: [ AudioStudioComponent ], exports: [ AudioStudioComponent ], providers: [ AudioService ] })
接下來要實現服務的消費者——AudioStudioComponent 了,步驟以下:
1.在構造函數中注入服務:
constructor(public audio: AudioService) { }
2.使用Add()方法添加音頻:
audio.Add({Url: '/assets/audio/唐人街.mp3', Title: '唐人街-林宥嘉',
Cover: '/assets/img/2219A91D.jpg'});
audio.Add({Url: '/assets/audio/天然醒.mp3', Title: '天然醒-林宥嘉',
Cover: '/assets/img/336076CD.jpg'});
Add方法添加的音頻若是是列表中僅有的一條音頻則會直接播放,因此如此添加兩條音頻會直接播放第一條音頻。
再在組件內實現一個Skip方法用於進度控制:
public Skip(e) { this.audio.Skip(e.layerX / document.getElementById('audio-total').getBoundingClientRect().width); }
如今運行項目:
音頻播放器的樣式是崩塌的...由於這個組件是筆者另外一個項目中直接copy過來了,在此demo項目中還沒加上移動端rem適配,尷尬,不過大概的效果是展示出來了。
完整項目代碼放在本人github上: https://github.com/yitimo/angular2-demo-yitim
4、總結:
總的來講ng2的服務光使用來講難度不高,關鍵在於如何來完美髮揮服務的特性,來作數據共享傳遞,以及封裝網絡請求等都是很好的選擇。另外本文沒有專門去講服務的一些問題點,但使用服務仍是有一些須要注意的地方的,好比只能在單個模塊中的provider中聲明,儘可能保持全局單例,以及在懶加載模塊中會建立子注入器等,實際項目中仍是要解決一些問題的。