AngularJS之使用控制器封裝業務邏輯
控制器的作用
我們知道,在AngularJS中,實現數據綁定的核心是scope對象。那么控制器又有什么用呢?
簡單地說,沒有控制器/controller,我們沒有地方定義業務模型。
回憶下ng-init指令。我們可以使用ng-init指令在scope對象上定義數據,比如:
- <div ng-init="sb={name:'somebody',gender:'male',age:28}">
- </div>
但是,ng-init的值是一個AngularJS表達式,沒有辦法定義方法。
控制器讓我們有機會在scope上定義我們的業務邏輯,具體說,可以使用控制器:
- 對scope對象進行初始化
- 向scope對象添加方法
在模板中聲明控制器
在一個HTML元素上使用ng-controller指令,就可以引入一個控制器對象:
- <div ng-controller="myController">...</div>
控制器的實現
控制器實際上就是一個JavaScript的類/構造函數:
- //控制器類定義
- var myControllerClass = function($scope){
- //模型屬性定義
- $scope.text = "...";
- //模型方法定義
- $scope.do = function(){...};
- };
- //在模塊中注冊控制器
- angular.module('someModule',[])
- .controller("myController",myControllerClass);
控制器的一次性
控制器構造函數僅在AngularJS對HTML文檔進行編譯時被執行一次。從這個角度看, 就更容易理解為何將控制器稱為對scope對象的增強:一旦控制器創建完畢,就意味着scope對 象上的業務模型構造完畢,此后就不再需要控制器了- scope對象接管了一切。
控制器對scope的影響
ng-controller指令總是創建一個新的scope對象:
在圖中,我們看到:
- ng-app指令引發$rootScope對象的創建。開始時,它是一個空對象。
- body元素對應的scope對象還是$rootScope。ng-init指令將sb對象掛在了$rootScope上。
- div元素通過ng-controller指令創建了一個新的scope對象,這個對象的原型是$rootScope。
- 因為原型繼承的關系,在do函數中對sb的引用指向$rootScope.sb。
初始化$scope對象
通常在應用啟動時,需要初始化scope對象上的數據模型。我們之前曾使用ng-init指令進行初始化, 而使用控制器則是更為規范的做法。
示例定義了一個ezController,利用這個控制器,我們對業務模型進行了初始化賦值:
示例:http://www.hubwiz.com/course/54f3ba65e564e50cfccbad4b/中“使用控制器封裝業務邏輯”第四頁
請注意,控制器僅僅負責在編譯時在scope對象上建立視圖對象vm,視圖對象和模板的綁定則是由 scope負責管理的。
向cope對象添加方法
業務模型是動態的,在數據之外,我們需要給業務模型添加動作。
在之前建立的業務模型上,我們增加一個隨機挑選的方法:shuffle,這個方法負責 從一個小型的名人庫中隨機的選擇一個名人來更新模型的sb屬性:
通過在button上使用ng-click指令,我們將模型的shuffle方法綁定到了鼠標點擊 事件上。試着用鼠標點擊【shuffle】按鈕,我們的模型將從庫里隨機的選出一個 名人,顯示在視圖里。
示例代碼參見:http://www.hubwiz.com/course/54f3ba65e564e50cfccbad4b/中“使用控制器封裝業務邏輯”第五頁。
別把任何代碼都塞到控制器里!
控制器的設計出發點是封裝單個視圖的業務邏輯,因此,不要進行以下操作:
- DOM操作
應當將DOM操作使用指令/directive進行封裝。
- 變換輸出形式
應當使用過濾器/filter對輸出顯示進行轉化。
- 跨控制器共享代碼
對於需要復用的基礎代碼,應當使用服務/service進行封裝