什么是ui-router
- ui-router是AngularUI庫最有用的組件之一(AngularUI庫由AngularJS社區構建)。它是一個第三方路由框架,允許通過狀態機制組織接口,而不是簡單的URL路由。
作用
- 和ngRoute功能一樣,可以定義在任意狀態內的模板都處在<ui-view>中
- 與ngRoute不同的是,每個模板中可以包含自己的<ui-view>中,也就是我們說的嵌套路由
如何使用
- 下面,將要向大家介紹下使用ui-router建立一個簡單的路由,涵蓋了ui-router基本的也是常用的方法。
- 首先,需要定義路由,可以使用.config方法,和ngRoute不同的是,路由是要設置在$routeProvider上, 而是將狀態設置在$stateProvider上,
$stateProvider.state(stateName, stateConfig)
stateName::字符串
stateConfig:object對象,可以設置url、template、controller等屬性
- 了解完定義狀態的用法,我們可以看一下實例代碼:
1 app.config(function($stateProvider) { 2 $stateProvider 3 .state('C1', { 4 url:'/C1', 5 template: '<h1>進入C1狀態</h1>' 6 7 }) 8 .state('C2', { 9 url: '/C2', 10 templateUrl: 'Htmls/C2.html' 11 12 }) 13 .state('C3', { 14 url: '/C3', 15 templateProvider: function() { 16 return '<h1>進入C3狀態</h1>'; 17 } 18 }) 19 });
- 上面代碼中,我們給狀態配置對象分配了三個狀態,“C1”、“C2”和"C3"。當應用程序狀態為以上三個狀態時,url會自動切換到定義的地址,而且也會顯示相應的html模板。其中,有三種顯示html模板的方式
template: 一個html內容字符串或一個能返回html字符串的函數, 如狀態C1處代碼;
templateUrl: 一個html模板的路徑字符串或者是一個能返回URL路徑字符串的函數,如狀態C2處代碼;
templateProvider:一個能返回URL路徑字符串的函數,如狀態C3處代碼;
- 現在,我們來寫一下index.html和app.js文件,實現一下ui-router:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title>index</title> 6 <link href="css/index.css" rel="stylesheet" /> 7 <script src="js/lib/angular/angular.min.js"></script> 8 <script src="js/lib/angular-ui-router/release/angular-ui-router.min.js"></script> 9 <script src="app.js"></script> 10 </head> 11 <body ng-app="TrialApp" ng-controller="mainController" style="background-color: lightblue;"> 12 <h1>index頁面</h1> 13 <div style="width: 80%; float: right;background-color: #C0C0C0;"> 14 <h1>路由區域</h1> 15 <ui-view> </ui-view> 16 </div> 17 </body> 18 </html>
- 建立一個定義TrialApp模塊文件app.js:
1 'use strict'; 2 // Define `TrialApp` module 3 var app = angular.module('TrialApp', ['ui.router']); 4 // Define routers 5 app.config(function($stateProvider) { 6 $stateProvider 7 .state('C1', { 8 url:'/C1', 9 template: '<h1>進入C1狀態</h1>' 10 11 }) 12 .state('C2', { 13 url: '/C2', 14 templateUrl: 'Htmls/C2.html' 15 16 }) 17 .state('C3', { 18 url: '/C3', 19 templateProvider: function() { 20 return '<h1>進入C3狀態</h1>'; 21 } 22 }) 23 });
- 這時,並不能一進入頁面就能看見路由的效果,需要我們通過寫代碼來激活狀態。激活state有3種方法:
1. 調用$state.go('stateName');方法;
2. 在html文檔中<ui-view>區域之外的地方,添加<a ui-sref='stateName'>stateName</a>鏈接,等頁面渲染之后可以通過點擊該鏈接進入所選狀態所對應的頁面;
3. 在地址欄中輸入state中定義過的url,隨后Enter直接訪問。
- 現在我們來演示一下上述方法中的前面兩種激活狀態的方法:
方法1: 如果需要在頁面一加載時就要顯示某一狀態,需要在app.js后面加一下代碼:
1 app.run(function($state) { 2 $state.go('C1'); 3 });
上述代碼是在加載該模塊的時候調用$state.go('C1');,以激活C1狀態。運行以后就是以下效果:

方法2:在html文檔中<ui-view>區域之外的地方,添加<a ui-sref='stateName'>stateName</a>鏈接,代碼如下:
1 <a ui-sref='C1'>C1</a><br /> 2 <a ui-sref='C2'>C2</a><br /> 3 <a ui-sref='C3'>C3</a>
由於上述效果有點丑,我們調整下html代碼:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title>index</title> 6 <link href="css/index.css" rel="stylesheet" /> 7 <script src="js/lib/angular/angular.min.js"></script> 8 <script src="js/lib/angular-ui-router/release/angular-ui-router.min.js"></script> 9 <script src="app.js"></script> 10 </head> 11 <body ng-app="TrialApp" ng-controller="mainController" style="background-color: lavender;"> 12 <h1>index頁面</h1> 13 <div style="width: 20%; float: left;background-color: lightgoldenrodyellow;text-align: center;"> 14 <a ui-sref='C1'>C1</a><br /> 15 <a ui-sref='C2'>C2</a><br /> 16 <a ui-sref='C3'>C3</a> 17 </div> 18 <div style="width: 80%; float: right;background-color: #C0C0C0;"> 19 <h1>路由區域</h1> 20 <ui-view> </ui-view> 21 </div> 22 </body> 23 </html>
以下是改良后的渲染效果,只要點擊

- 在本文最后, 演示一下如何在state中加載controller
controller: 1. 外部文件Controller的名字,注意文件命名時要把controller和前面的單詞區分開,比如“MainController”, 最好前面一個單詞首字母大寫,Controller也是一樣,方便解析
2. 直接寫一個函數
現在,我們把app.js的代碼再編輯下,如下:
1 'use strict'; 2 // Define `TrialApp` module 3 var app = angular.module('TrialApp', ['ui.router']); 4 // Define routers 5 app.config(function($stateProvider) { 6 $stateProvider 7 .state('C1', { 8 url:'/C1', 9 template: '<h4>進入C1狀態</h4>', 10 controller:'C1Controller' 11 }) 12 .state('C2', { 13 url: '/C2', 14 templateUrl: 'Htmls/C2.html', 15 controller: function() { 16 this.test = 'world!'; 17 }, 18 controllerAs: 'C2Ctrl' 19 }) 20 .state('C3', { 21 url: '/C3', 22 templateProvider: function() { 23 return '<h4>進入C3狀態</h4><br />' 24 + '<p>{{t}}</p>'; 25 }, 26 controller: function($scope) { 27 $scope.t = 'C3Controller is on!'; 28 } 29 }) 30 }); 31 app.controller('mainController', function() { 32 return alert('hello!'); 33 }); 34 app.run(function($state) { 35 $state.go('C1'); 36 });
另外創建一個js文件“C1Controller”,代碼如下:
1 'use strict'; 2 //Define `C1Controller` 3 app.controller('C1Controller', function() { 4 alert('C1Controller is on!'); 5 });
C2.html代碼修改如下:
1 <h4>進入狀態C2</h4><br /> 2 <p>Hello, {{C2Ctrl.test}}</p>
下面是整個應用的效果:

- 上面的代碼使用了上述兩種方法加載了controller。對於第一種方法,記得創建完相應的js外部文件之后,在index.html加上該文件的路徑,不然,編譯器在解析代碼的時候找不到名字所對應的文件會報錯Error: [$controller:ctrlreg],
這是都因為controller文件沒有被注冊成功,所以在編寫完之后要注意檢查這一點。
- 還有一點值得注意的是,在狀態C2和C3中,分別都用了內置controller的方法,在方法中創建變量,並在對應頁面中顯示其值。
在C2中,用了this.test(this指當前對象)聲明並初始化變量,為了能在C2對應頁面中顯示變量值,需要將controller設置別別名,controllerAs: ‘C2Ctrl’,
然后在對應html模板中用{{C2Ctrl.test}}
而在C3中,在controller中用$scope創建變量,在對應html模板中用{{t}},這里$scope對應的就是該controller的作用域,所以在與其關聯的html文本中,直接寫出該變量即可。
- 那這里,有人也許會問,我在這里也寫一個contorllerAs,給controller取個別名,然后再{{controller.變量}}行不行?
答案是不行(親測有效)。記得AngularJS官網的phonecatApp示例中,曾提到過一句話,如果應用規模大,controller數量多而雜的情況下,在設置controller過程中,盡量避免$scope。
個人覺得是因為,$scope代表一個controller的作用域,如果有多個controller,那就會有多個$scope,那如果大家都有$scope,那放在一起,誰會清楚這是那個作用域的屬性?所以個人
覺得controller給controller起個別名是一個比較好的方法,這樣一眼就是識別這是哪個controller,方便代碼后期維護,也方便別人(你的同事們)解讀。
- 好了,今天主要是對ui-router入門的講解。希望能通過這一簡單的示例,讓大家能對ui-router的一個基本原理有所了解。下一次將會進階地講ui-router的東西,比如多個視圖、路由嵌套及與ngRoute的對比。如果本文有哪些講解得不夠細致或有錯誤的地方,歡迎讀者指正。


