歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> AngularJS入門講解3:$http服務和路由講解

AngularJS入門講解3:$http服務和路由講解

日期:2017/3/1 9:34:08   编辑:Linux編程

上一課的例子中,我們的模型數據是硬編碼的,也就是說,我們的數據不是從服務器請求回來的。

這裡,我們先講解,如何從服務器獲取數據:

function PhoneListCtrl($scope, $http) {
  $http.get('phones/phones.json').success(function(data) {
    $scope.phones = data;
  });

  $scope.orderProp = 'age';
}

上一課的例子,我們只需要改寫這個控制器構造函數就行了。

$http向Web服務器發起一個HTTP GET請求,獲取phone/phones.json。AngularJS會自動檢測這個應答是什麼格式的,並且幫我們解析出來!

為了使用AngularJS的服務,你只需要在控制器的構造函數裡面傳入所需服務的名字。

當控制器構造的時候,AngularJS的依賴注入器會將這些服務注入到你的控制器中。

由於AngularJS是通過控制器構造函數的參數名字來推斷依賴服務名稱的。所以如果你要壓縮PhoneListCtrl控制器的JS代碼,它所有的參數也同時會被壓縮,這時候依賴注入系統就不能正確的識別出服務了。

為了克服壓縮引起的問題,只要在控制器函數裡面給$inject屬性賦值一個依賴服務標識符的數組,就像:

PhoneListCtrl.$inject = ['$scope', '$http'];
另一種方法也可以用來指定依賴列表並且避免壓縮問題——使用Javascript數組方式構造控制器:把要注入的服務放到一個字符串數組(代表依賴的名字)裡,數組最後一個元素是控制器的方法函數:

var PhoneListCtrl = ['$scope', '$http', function($scope, $http) { /* constructor body */ }];
上面提到的兩種方法都能和AngularJS可注入的任何函數完美協作,要選哪一種方式完全取決於你們項目的編程風格,建議使用數組方式。

然後,我們為手機列表的手機數據項添加縮略圖以及鏈接:

[
  {
    ...
    "id": "motorola-defy-with-motoblur",
    "imageUrl": "img/phones/motorola-defy-with-motoblur.0.jpg",
    "name": "Motorola DEFY\u2122 with MOTOBLUR\u2122",
    ...
  },
  ...
]

html改成這樣:

...
<ul class="phones">
  <li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
    <a href="#/phones/{{phone.id}}" class="thumb">

      <img ng-src="{{phone.imageUrl}}">

    </a>
    <a href="#/phones/{{phone.id}}">{{phone.name}}</a>
    <p>{{phone.snippet}}</p>
  </li>
</ul>
...

為每條記錄添加圖片,只需要使用ngSrc指令代替<img>的src屬性標簽就可以了。因為如果我們用一個正常src屬性來進行綁定(<img class="diagram" src="{{phone.imageUrl}}">),浏覽器會把AngularJS的{{ 表達式 }}標記直接進行字面解釋,這時會發起一個向非法url:http://localhost:8000/app/{{phone.imageUrl}}的請求,因為浏覽器載入頁面時,同時也會請求載入圖片。有了這個ngSrc指令,就會避免產生這種情況。

上面的應用只給我們的用戶提供了一個簡單的界面(一張所有手機的列表),並且所有的模板代碼位於index.html文件中。

最後,我們增加一個能夠顯示我們列表中每一部手機詳細信息的頁面。

為了增加詳細信息視圖,我們可以拓展index.html來同時包含兩個視圖的模板代碼,但是這樣會很快給我們帶來巨大的麻煩。相反,我們要把index.html模板轉變成“布局模板”。這是我們應用所有視圖的通用模板。其他的“局部布局模板”,根據當前的“路由”被填入,從而形成一個完整視圖展示給用戶。

AngularJS中的路由是通過$routeProvider來聲明的,它是$route服務的提供者。這項服務使得控制器、視圖模板與當前浏覽器的URL可以輕易集成。它允許我們使用浏覽器的歷史(回退或者前進導航)和書簽。

angular運行時,它會創建一個注入器,後面所有依賴注入的服務都會需要它。這個注入器自己並不知道$http和$route是干什麼的,注入器唯一的職責是載入指定的服務模塊,在這些模塊中注冊所有定義的服務提供者,並且當需要時給一個指定的函數注入服務。這些服務通過它們的提供者“懶惰式”(需要時才加載)實例化。

提供者提供服務實例並且對外提供API接口的對象,它可以被用來控制一個服務的創建和運行。對於$route服務來說,$routeProvider對外提供了API接口,通過API接口允許你為你的應用程序定義路由規則。

為了給我們的應用配置路由,我們需要給應用創建一個模塊。

angular.module('phonecat', []).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl}).
      when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}).
      otherwise({redirectTo: '/phones'});
  }]);

我們把這個模塊定義為phonecat,並且通過使用config方法,我們把$routeProvider注入到我們的配置函數中,並且使用$routeProvider.when方法來定義我們的路由規則。

我們的路由規則定義如下:

(1)當URL 映射段為/phones時,手機列表視圖會被顯示出來。為了構造這個視圖,AngularJS會使用phone-list.html模板和PhoneListCtrl控制器。
(2)當URL 映射段為/phone/:phoneId時,手機詳細信息視圖被顯示出來。這裡:phoneId是URL的變量部分。為了構造手機詳細視圖,AngularJS會使用phone-detail.html模板和PhoneDetailCtrl控制器。

(3)otherwise({redirectTo: '/phones'})語句使得當浏覽器地址不能匹配我們任何一個路由規則時,觸發重定向到/phones。

我們重用之前創造過的PhoneListCtrl控制器,同時我們為手機詳細視圖添加一個新的PhoneDetailCtrl控制器。

為了讓我們新創建的模塊運行起來,我們需要在ngApp指令的值上指明模塊的名字:

<!doctype html>
  <html lang="en" ng-app="phonecat">
    ...

  </html>

新的PhoneDetailCtrl控制器:

function PhoneDetailCtrl($scope, $routeParams) {
  $scope.phoneId = $routeParams.phoneId;
}

注意到在第二條路由聲明中:phoneId參數的使用。所有以:符號聲明的變量(此處變量為phones)都會被提取,然後存放在$routeParams對象中。

$route服務通常和ngView指令一起使用。ngView指令的角色是為當前路由把對應的視圖模板載入到布局模板中。

<html lang="en" ng-app="phonecat">
  <head>
    ...
    <script src="lib/angular/angular.js"></script>
    ...
  </head>
  <body>

    <div ng-view>

    </div>

  </body>
</html>

注意,我們把index.html模板裡面大部分代碼移除,我們只放置了一個<div>容器,這個<div>具有ng-view屬性。我們刪除掉的代碼現在被放置在phone-list.html模板中:

<div class="container-fluid">
<div class="row-fluid">
<div class="span2">

Search: <input ng-model="query">
Sort by:
<select ng-model="orderProp">
<option value="name">Alphabetical</option>
<option value="age">Newest</option>
</select>

</div>
<div class="span10">

<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
<a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a>
<a href="#/phones/{{phone.id}}">{{phone.name}}</a>
<p>{{phone.snippet}}</p>
</li>
</ul>

</div>
</div>
</div>

同時我們為手機詳細信息視圖添加一個占位模板。

TBD: detail view for {{phoneId}}

大家注意到我們上面的兩個模板中沒有添加PhoneListCtrl或PhoneDetailCtrl控制器屬性!

這樣就實現了一個基於angular的多視圖的應用程序。

AngularJS權威教程 清晰PDF版 http://www.linuxidc.com/Linux/2015-01/111429.htm

希望你喜歡,並分享我的工作~帶你走近AngularJS系列

  1. 帶你走近AngularJS - 基本功能介紹 http://www.linuxidc.com/Linux/2014-05/102140.htm
  2. 帶你走近AngularJS - 體驗指令實例 http://www.linuxidc.com/Linux/2014-05/102141.htm
  3. 帶你走近AngularJS - 創建自定義指令 http://www.linuxidc.com/Linux/2014-05/102142.htm

如何在 AngularJS 中對控制器進行單元測試 http://www.linuxidc.com/Linux/2013-12/94166.htm

在 AngularJS 應用中通過 JSON 文件來設置狀態 http://www.linuxidc.com/Linux/2014-07/104083.htm

AngularJS 之 Factory vs Service vs Provider http://www.linuxidc.com/Linux/2014-05/101475.htm

AngularJS —— 使用 ngResource、RESTful APIs 和 Spring MVC 框架提交數據 http://www.linuxidc.com/Linux/2014-07/104402.htm

AngularJS 的詳細介紹:請點這裡
AngularJS 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved