AngularJS 的常用特性(五)

shaopiing發表於2016-05-22

13、使用路由和 $location 切換檢視

  對於一些單頁面應用來說,有時候需要為使用者展示或者隱藏一些子頁面檢視,可以利用 Angular 的 $route 服務來管理這種場景。

  你可以利用路由服務來定義這樣的一種東西:對於瀏覽器所指向的特定 URL,Angular 將會載入並顯示一個模板,並例項化一個控制器來為模板提供內容。

  在應用中可以呼叫 $routeProvider 服務上的函式來建立路由,把需要建立的路由當成一個配置塊傳給這些函式即可。虛擬碼如下:

1 var someModule = anguler.module('someModule', [...module dependencies...]);
2 
3 someModule.config(function($routeProvider) {
4     $routeProvider.
5         when('url', {controller : aController, templateUrl : '/path/to/template'}).
6         when(...other mappings for your app...).
7         ...
8         otherwise(...what to do if nothing else matches);
9 });    

  以上程式碼中,當瀏覽器中的 URL 變成指定的取值時,Angular 將會載入 /path/to/template 路徑下的模板,然後把這個模板中的根元素關聯到 aController 上,最後一行中的 otherwise 呼叫可以告訴路由,在沒有匹配到任何東西時跳轉到這裡。

  下面構建一個小例子,但是需要把程式碼放到 web 伺服器上中。

  index.html

 1 <html ng-app="AMail">
 2     <head>
 3     </head>
 4     <body>
 5         <h1>A-Mail</h1>
 6         <div ng-view></div>
 7         <script src="../src/angular.js"></script>
 8         <script src="../src/angular-route.js"></script>
 9         <script src="controller.js"></script>
10     </body>
11 </html>

  list.html

 1 <table>
 2     <tr>
 3         <td><strong>Sender</strong></td>
 4         <td><strong>Subject</strong></td>
 5         <td><strong>Date</strong></td>
 6     </tr>
 7     <tr ng-repeat="message in messages">
 8         <td>{{message.sender}}</td>
 9         <td><a href="#/view/{{message.id}}">{{message.subject}}</a></td>
10         <td>{{message.date}}</td>
11     </tr>
12 </table>

  detail.html

 1 <div><strong>Subject: </strong>{{message.subject}}</div>
 2 <div><strong>Sender: </strong>{{message.sender}}</div>
 3 <div><strong>Date: </strong>{{message.date}}</div>
 4 <!-- ng-bind 效能不如 {{}},儘量只在 index.html 頁面使用 ng-bind,避免花括號一閃而過-->
 5 <div>
 6     <strong>To: </strong>
 7     <span ng-repeat="recipient in message.recipients">{{recipient}}</span>
 8 </div>
 9 <div>{{message.message}}</div>
10 <a href="#/">back to message list</a>

  controller.js

 1 //為核心的 AMail 服務建立模組
 2 var aMailServices = angular.module('AMail', ['ngRoute']);
 3 
 4 //在 URL,模板和控制器之間建立對映關係
 5 aMailServices.config(function($routeProvider) {
 6     $routeProvider.
 7     when('/', {
 8         controller: ListController,     // 全域性的 function 方式去找 Controller
 9         templateUrl: 'list.html'
10     }).
11     //注意,為了建立詳情檢視,在 id 前面加了一個冒號,從而指定了一個引數化的 URL 元件
12     when('/view/:id', {
13         controller: 'DetailController', // 用註冊的方式去找 Controller
14         templateUrl: 'detail.html'
15     }).
16     otherwise({
17         redirectTo: '/'
18     });
19 });
20 
21 //一些虛擬郵件
22 messages = [{
23         id: 0, sender: 'jean@somecompany.com', subject: 'Hi there, old friend',
24         date: 'Dec 7, 2013 12:32:00', recipients: ['greg@somecompany.com'],
25         message: 'Hey, we should get together for lunch sometime and catch up.'
26         + 'There are many things we should collaborate on this year.'
27     }, {
28         id: 1, sender: 'maria@somecompany.com', subject: 'Where did you leave my laptop?',
29         date: 'Dec 7, 2013 8:15:12', recipients: ['greg@somecompany.com'],
30         message: 'I thought you were going to put it in my desk drawer.'
31         + 'But it does not seem to be there.'
32     }, {
33         id: 2, sender: 'bill@somecompany.com', subject: 'Lost python',
34         date: 'Dec 6, 2013 20:35:02', recipients: ['greg@somecompany.com'],
35         message: "Nobody panic, but my pet python is missing from her cage."
36         + "She doesn't move too fast, so just call me if you see her."
37     }];
38     
39 //把郵件釋出給郵件列表模板,注意兩種方式,建議使用下面註冊的方式,避免全域性的 function 汙染
40 function ListController($scope) {
41     $scope.messages = messages;
42 }
43 
44 aMailServices.controller('DetailController', function($scope, $routeParams) {
45     $scope.messages = messages[$routeParams.id];
46 });

  效果如下:

  

14、與伺服器互動

  真正的應用需要和真實的伺服器進行互動,Angular 中提供了一個叫做 $http 的服務。它提供了一個可擴充套件的抽象方法列表,使得與伺服器的互動更加容易。它支援 HTTP、JSONP 和 CORS 方式。它還包含了安全性支援,避免 JSON 格式的脆弱性和 XSRF。可以讓你輕鬆地轉換請求和響應資料,甚至還實現了簡單的快取。

  返回的響應資料示例如下:

 1 [
 2     {
 3         "id" : 0,
 4         "title" : "Paint pots",
 5         "description" : "Pots full of paint",
 6         "price" : 3.95
 7     },
 8     {
 9         "id" : 1,
10         "title" : "Polka dots",
11         "description" : "Dots with that polka groove",
12         "price" : 12.95
13     },
14     {
15         "id" : 2,
16         "title" : "Pebbles",
17         "description" : "Just little rocks, really",
18         "price" : 6.95
19     }
20 ]

  我們可以像下面這樣編寫查詢程式碼:

1 function ShoopingController($scope, $http) {
2     $http.get('/products').success(function (data, status, headers, config) {
3         $scope.items = data;
4     });
5 }

  然後就可以應用到模板中了。

15、使用指令修改 DOM

  指令擴充套件了 HTML 語法,同時它也是使用自定義的元素和屬性把行為和 DOM 轉換關聯到一起的方式。通過這些指令,可以建立可複用的 UI 元件,配置你的應用,並且可以做到你能想象到的幾乎所有事情,這些事情都可以在你的 UI 模板中實現。所以說,自定義指令是 Angular 的精髓

  與服務一樣,你可以通過模組物件的 API 來定義指令,只要呼叫模組例項的 directive() 函式即可,其中 directiveFunction 是一個工廠函式,用來定義指令的特性。

var appModule = angular.module('appModule', [...]);
appModule.directive('directiveName', directiveFunction);

  指令的東西很多,以後詳解,這裡先舉個例子,感受下指令的魅力。

  編寫一個非常簡單的指令:一個 <hello> 元素,它會把自己替換成 <div>Hi there</div>。

  先看指令:

1 var appModule = angular.module('app', []);
2 
3 appModule.directive('hello', function () {
4     return {
5         restrict: 'E',
6         template: '<div>Hi there</div>',
7         replace: true
8     };
9 });

  這裡,restrict 屬性表示描述指令的風格,E 表示允許使用元素的形式;template 屬性表示需要替換的內容;replace 屬性設定為 true 表示會用 HTML 內容來替換模板。

  可以在模板中這樣使用它:

1 <html lang="en" ng-app="app">
2     <script src="../src/angular.js"></script>
3     <script src="directive.js"></script>
4     <body>
5         <hello></hello>
6     </body>
7 </html>

  把以上內容載入到瀏覽器中,就會顯示

Hi there

16、校驗使用者輸入

  Angular 自動為 <form> 元素增加了一些好用的特性,使其更適合單頁面應用。其中一個特性是,Angular 允許你為表單中的輸入元素定義一個合法的狀態,並且只有當所有元素都是合法狀態時才允許提交表單。

  控制器如下:

 1 var addUser = angular.module('AddUserModule', []);
 2 
 3 addUser.controller('AddUserController', function ($scope) {
 4     $scope.message = '';
 5 
 6     $scope.addUser = function () {
 7         // 這裡把 user 真正儲存到資料庫中
 8         $scope.message = 'Thanks, ' + $scope.user.first + ', we added you!';
 9     }
10 });

  模板如下:

 1 <html ng-app="AddUserModule">
 2     <body>
 3         <form name="addUserForm" ng-controller="AddUserController">
 4             <div ng-show="message">{{message}}</div>
 5             <div>First name: <input name="firstName" ng-model="user.first" required></div>
 6             <div>Last name: <input ng-model="user.last" required></div>
 7             <div>Email: <input type="email" ng-model="user.email" required></div>
 8             <div>Age: <input type="number" ng-model="user.age" ng-maxlength="3" ng-minlength="1"></div>
 9             <div><button ng-click="addUser()" ng-disabled="!addUserForm.$valid">Submit</button></div>
10         </form>
11         <script src="../src/angular.js"></script>
12         <script src="submit.js"></script>
13     </body>
14 </html>

  在控制器中,可以通過 $valid 屬性獲取表單的校驗狀態,當表單中的所有輸入項都合法時,Angular 將會把這個屬性設定為 true,否則沒有輸入完成時禁用了 Submit 按鈕。

  

PS:到目前為止,已經介紹了 Angular 框架的幾乎所有常用特性,掌握了這個《常用特性》系列的文章,就算是入門了,加油!

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

相關文章