原文連接 : How to write AngularJS controller using TypeScript?
原文做者 : Siddharth Pandey
譯者 : 李林璞(web前端領域)
譯者注:翻譯若有疏漏,歡迎指出!感謝!轉載請保留此頭部。javascript
AngularJS 有許多強大的特性,其中之一即是 Controller。在這篇文章裏,我將介紹如何使用 TypeScript 去編寫 AngularJS 的 Controller。html
Controller 一般用來加強 AngularJS 做用域(Scope)。當一個 Controller 經過 ng-controller
指令鏈接到 DOM 上的時候,Angular 將使用指定的 Conroller 函數初始化一個新的 Controller 對象。一個新的子 scope 將被建立並做爲 $scope
變量注入到 Controller 的構造函數當中。前端
有兩個選項將 Controller 鏈接到視圖當中,一種是 Controller 做爲語法,另一種是使用 $scope
。若是使用 Controller 語法,Controller 實例將被分配一個在新做用域上的屬性。java
要想知道類型定義,看看這個使人吃驚的倉庫,它收集了幾乎全部流行的 JavaScript 庫。這些類型定義可讓咱們獲得任何編譯時錯誤和 IDE 的智能支持。我使用 Visual Studio 和 Visual Code,它們都對 TypeScript 有很好的支持。git
正如上面提到的,AngularJS 只要在被請求的時候都將建立一個Controller 實例。因此,一個 Controller 可使用 TypeScript 裏的類去定義,就像咱們所知道的,一個類是能夠被實例化的。讓咱們來使用在視圖裏 Controller 做爲語法的方法來定義一個 Dashboard Controller。下面的代碼沒有使用 $scope
服務。angularjs
interface IDashboardVm { news: { title: string, description: string }; messageCount: number; people: Array<any>; title: string; getMessageCount: () => ng.IPromise<number>; getPeople: () => ng.IPromise<Array<any>>; } class DashboardController implements IDashboardVm { static $inject: Array<string> = ['dataservice']; constructor(private dataservice: app.core.IDataService) { this.getMessageCount(); this.getPeople(); } news = { title: 'News', description: 'Internal server team is excited about AngularJS, TypeScript & JavaScript' }; messageCount: number = 0; people: Array<any> = []; hubsSummary: Array<any> = []; title: string = 'Dashboard'; getMessageCount() { return this.dataservice.getMessageCount().then((data) => { this.messageCount = data; return this.messageCount; }); } getPeople() { return this.dataservice.getPeople().then((data) => { this.people = data; return this.people; }); } } angular.module('app.dashboard').controller('DashboardController', DashboardController);
利用 TypeScript 的強類型特徵,最好建立一個包含全部和視圖相關成員和行爲的接口。這就可使爲一個 Controller 定義實現變得容易,並且這個接口若是須要就能夠作成一個抽象方法在其餘地方使用了。因此,上面代碼裏我建立了一個名爲 IDashboardVm
的接口。github
接着,名爲 DashboardController
的 Controller 實現了這個接口並給每一個成員定義了默認狀態。看這個類的靜態變量 $inject
,它告訴了 AngularJS DI 在初始化這個 Controller 以前注入哪些依賴。而後構造器在須要的依賴的相同順序定義了參數當它們被注入到那些參數的時候。web
類所提到的依賴都是至關直接了當的,假設 dataservice
是一個自定義的 AngularJS 服務,它封裝了全部對服務器發起的 HTTP 請求。根據接口裏的每一個定義,接下來咱們要爲這些行爲定義實現,內部調用 dataservice
方法。它使用了 promises
去返回待會兒要分配到 Controller 成員上去控制狀態的響應。typescript
真正重要的是要注意使用 Angular 的模塊 API 註冊這個 Controller 的位置。上面的代碼裏,首先定義了類而後完成其註冊。若是這個順序交換的話,Angular 就將找不到咱們這個 Controller 的實現了。當使用一個 JavaScript 構造函數就能夠很好地解決問題,由於函數提高起到了很重要的做用。promise
下面是這個 Controller 如何在 Angular-UI UI-Router 中使用的代碼片斷,但若是你想使用 Angular 內置路由模塊的話概念是同樣的。注意,這隻展現了使用 controllerAs
語法進行配置的部分。
config: { url: '/', templateUrl: 'app/dashboard/dashboard.html', controller: 'DashboardController', controllerAs: 'vm', title: 'dashboard', }
若是你想使用 $scope
服務的話,那麼就能夠像下面的代碼片斷那樣擴展上面的接口。這將確保全部 IScope 有的成員能夠經過接口訪問到。使用這個方法還須要改變一下 Controller 類的實現,由於如今它須要 $scope
服務的依賴了。自定義接口類型接着就能夠在構造器使用 $scope
參數得到強類型和智能支持了。
interface IDashboardVm extends angular.IScope { news: { title: string, description: string }; messageCount: number; people: Array<any>; title: string; getMessageCount: () => ng.IPromise<number>; getPeople: () => ng.IPromise<Array<any>>; }
若是你想學到更多有關如何整合 AngularJS 和 TypeScript 的知識,能夠看看個人 AngularJS 文章。若是你想學習其餘一些特別的東西能夠聯繫我,我會嘗試寫相關文章的。