AngularJS 的常用特性(四)

shaopiing發表於2016-05-22

11、使用 Module(模組) 組織依賴關係

  Angular 裡面的模板,提供了一種方法,可以用來組織應用中一塊功能區域的依賴關係;同時還提供了一種機制,可以自動解析依賴關係(又叫依賴注入),一般來說,我們把這些叫做依賴服務,因為它們會負責為應用提供特殊的服務。

  例如,如果購物站點中的一個控制器需要從伺服器中獲取一個商品列表 Items,來處理從伺服器獲取商品的工作。進而,Items 物件就需要以某種方式與伺服器上的資料庫進行互動,可以通過 XHR 或者 WebSocket。

  如果,在沒有模組的情況下,那麼程式碼看起來就像下面這樣:

function ItemsViewController($scope) {
    // 向伺服器發起請求
    ...
    // 解析響應並放入 Item 物件
    ...
    // 把 Items 陣列設定到 $scope 上,這樣檢視才能夠顯示它
    ...
}

  雖然這麼做可以執行,但是存在一些潛在的問題:

  • 如果其他控制器也需要從伺服器獲取 Items,那麼我們只能把這段程式碼重寫一遍,程式碼維護工作增大難度;
  • 加上其他的一些因素,例如伺服器認證、解析資料的複雜性,會使控制器物件很難劃分出一個合理的功能邊界,並且程式碼閱讀起來更加困難;
  • 增加單元測試的難度,要測試這段程式碼,必須啟動一個真正的伺服器。

  利用模組和模組內建的依賴注入功能,我們可以把控制器寫得更加簡單,示例如下:

function ShoppingController($scope, Items) {
    $scope.items = Items.query();
}

  這樣會很簡單而且方便,只需要把 Items 物件定義成了一個服務

  服務都是單例的物件,Angular 內建了很多服務,例如 $location 服務,用來和瀏覽器的位址列進行互動;$route 服務,用來根據 URL 地址的變化切換檢視;還有 $http 服務,用來和伺服器進行互動。

  你也可以自定義自己的服務,但最好不要以 $ 開頭,因為 Angular 內建的服務是以 $ 符號開頭的,以免引起衝突。

  你可以使用模型物件的 API 來定義服務,如下表格:

  ——————————————————————————————————————————————————————————————————————

  函式                     |  定義
  ——————————————————————————————————————————————————————————————————————

  provider(name, Object OR constructor())   | 一個可配置的服務,如果你傳遞了一個 Object 作為引數,那麼該物件必須帶有一個名為 $get 的函式,

                         |  該函式需要返回服務的名稱。否則,認為你傳遞的是一個建構函式,呼叫建構函式會返回服務例項物件。

  ——————————————————————————————————————————————————————————————————————

  factory(name, $getFunction())         |  一個不可配置的服務,需要你指定一個函式,當呼叫這個函式的時候,會返回服務的例項。

                         |  可以用把它看成 provider (name, { $get: $getFunction()}) 的形式

  ——————————————————————————————————————————————————————————————————————

  service(name, constructor())        |  一個不可配置的服務,與上面 provider 函式的constructor 引數類似,呼叫它可以建立服務例項

  ——————————————————————————————————————————————————————————————————————

  下面用 factory() 的方式編寫服務:

 1 // 建立一個模型用來支撐我們的購物檢視
 2 var shoppingModule = angular.module('ShoppingModule', []);
 3 
 4 // 設定好服務工廠,用來建立我們的 Items 介面,以便訪問服務端資料庫
 5 shoppingModule.factory('Items', function () {
 6     var items = {};
 7     items.query = function () {
 8         return [
 9             {title: 'Paint', description: 'Pots full of paint', price: 3.95},
10             {title: 'Polka', description: 'Dots with polka', price: 2.95},
11             {title: 'Pebbles', description: 'Just little rocks', price: 6.95}
12         ];
13     };
14     return items;
15 });

  控制器就很簡單了,但是需要注入 Items 物件:

1 shoppingModule.controller('ShoppingController', function ($scope, Items) {
2     $scope.items = Items.query();
3 });

  頁面可以寫個很簡單的如下:

 1 <html ng-app="ShoppingModule">
 2     <body ng-controller="ShoppingController">
 3         <script src="../src/angular.js"></script>
 4         <script src="factory.js"></script>
 5         <h1>Shop!</h1>
 6         <table>
 7             <tr ng-repeat="item in items">
 8                 <td>{{item.title}}</td>
 9                 <td>{{item.description}}</td>
10                 <td>{{item.price | currency}}</td>
11             </tr>
12         </table>
13     </body>
14 </html>

  效果如下:

  

12、使用過濾器格式化資料

   你可以用過濾器來宣告應該如何變換資料格式,然後再顯示給使用者,只要在模板中使用一個插值變數即可,過濾器的語法如下:

{{ expression | filterName : parameter1 : ... parameterN}}

  Angular 的內建過濾器,比如 currency:

{{12.9 | currency}}

  顯示結果為:

$12.90

  還有其他過濾器,比如 date、number、uppercase 等,可以連用:

{{12.9 | currency | number : 0}}

  顯示結果為:

$13

  當然,我們經常需要自定義過濾器,比如我們需要為標題文字建立首字母大寫的字串,編寫過濾器如下:

 1 var homeModule = angular.module('HomeModule', []);
 2 
 3 homeModule.filter('titleCase', function () {
 4     return function (input) {
 5         var words = input.split(' ');
 6         for (var i = 0; i < words.length; i++) {
 7             words[i] = words[i].charAt(0).toUpperCase() + words[i].slice(1);
 8         }
 9         return words.join(' ');
10     };
11 });
12 
13 homeModule.controller('HomeController', function ($scope) {
14     $scope.pageHeading = 'behold the majesty of your page title';
15 });

  簡單的模板頁面:

1 <html>
2     <body ng-app="HomeModule" ng-controller="HomeController">
3         <script src="../src/angular.js"></script>
4         <script src="filter.js"></script>
5         <h1>{{pageHeading | titleCase}}</h1>
6     </body>
7 </html>

  顯示結果如下:

  

特別感謝《用 AngularJS 開發下一代 Web 應用》

相關文章