[TOC]
# 路由狀態管理
## ui-router以狀態為核心
ui-router 的工作原理非常類似于 Angular 的路由控制器,但它只關注狀態。
* 在應用程序的整個用戶界面和導航中,一個狀態對應于一個頁面位置
* 通過定義controller、template和view等屬性,來定義指定位置的用戶界面和界面行為
* 通過嵌套的方式來解決頁面中的一些重復出現的部位
## 加載路由模塊
### 路由js文件加載
~~~
bower install angular-ui-router --save
~~~
### 項目模塊加載依賴
~~~
angular.module('myapp', ['ui.router']);
~~~
## 項目模塊中配置項目路由
### 使用Angular模塊對象的config方法配置
一般會在Angular的config方法中配置路由,config方法需要依賴兩個對象$stateProvider, $urlRouterProvider
~~~
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
});
~~~
## 路由狀態管理
### $stateProvider對象的state方法基本用法
理由狀態管理使用的是$stateProvider對象的state方法
~~~
//參數1:String 路由名稱
//參數2:Object 路由狀態對象配置
$stateProvider.state('contacts',{});
~~~
## 路由狀態模板屬性Templates 模板
### 方法一:配置template屬性,指定一段 HTML 字符串,這人是設置模板的最簡單的方式
【js文件】
~~~
angular.module('myapp', ['ui.router']);
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home',{
template:'<h1>這里是HZJ</h1>'
});
});
~~~
【html文件】
~~~
<div ng-controller="indexCtl">
<!--使用ui-sref指令綁定路由名稱-->
<button ui-sref="home">點擊</button>
<hr>
<!--使用ui-view【A】指令顯示路由模板內容,并且自動產生作用域-->
<div ui-view></div>
<hr>
<!--ui-view指令也可以使用【E】并且自動產生作用域-->
<ui-view></ui-view>
</div>
~~~
### 方法二:配置templateUrl屬性,來加載指定位置的模板,這是設置模板的常用方法。
templateUrl的值也可以是一個函數返回的url,函數帶一個預設參數stateParams。
【js文件templateUrl字符串】
~~~
angular.module('myapp', ['ui.router']);
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home',{
templateUrl:'homeTpl.html'
});
});
~~~
【js文件使用templateUrl函數】
~~~
angular.module('myapp', ['ui.router']);
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home',{
//templateUrl可以是一個函數,然后由函數返回一個字符串
templateUrl:function (stateParams) {
return 'homeTpl.html';
}
});
});
~~~
### 方法三:通過templateProvider函數返回模板的 HTML。
如果想在狀態被激活前,讓<ui-view>有一些默認的內容,當狀態被激活之后默認內容將被狀態對應的模板替換。
【js文件,使用templateProvider函數】
~~~
angular.module('myapp', ['ui.router']);
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home',{
//使用templateProvider返回一個模板
templateProvider: function ($timeout) {
return $timeout(function () {
return '<h1>dddddddddd</h1>'
}, 100);
}
});
});
~~~
【html文件,在路由結果還沒有在ui-view渲染時,默認寫點html】
~~~
<div ng-controller="indexCtl">
<!--使用ui-sref指令綁定路由名稱-->
<button ui-sref="home">點擊</button>
<hr>
<!--使用ui-view【A】指令顯示路由模板內容,并且自動產生作用域-->
<div ui-view>
<h1>這里是路由結果還沒有加載的默認結果嘿嘿</h1>
</div>
</div>
~~~
## 路由狀態激活和渲染
【項目結構】

【app.js文件】
~~~
angular.module('myapp', ['ui.router']);
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home',{
templateUrl:'homeTpl.html'
});
});
~~~
【homeTpl.html文件】
~~~
<h1>這里是home</h1>
~~~
【index.html文件】
~~~
<!DOCTYPE html>
<html lang="en" ng-app="myapp">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="css/mystyle.css">
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-ui-router/release/angular-ui-router.js"></script>
<script src="app.js"></script>
<script src="indexCtl.js"></script>
</head>
<body>
<div ng-controller="indexCtl">
<!--使用ui-sref指令綁定路由名稱-->
<button ui-sref="home">點擊</button>
<!--任何標簽都可以使用ui-sref指令-->
<a ui-sref="home">HOME頁面</a>
<button ng-click="gotoHome()">使用$state.go方法</button>
<hr>
<!--使用ui-view【A】指令顯示路由模板內容,并且自動產生作用域-->
<div ui-view>
<h1>這里是路由結果還沒有加載的默認結果嘿嘿</h1>
</div>
</div>
</body>
</html>
~~~
【indexCtl.js】
~~~
//控制器indexCtl
angular.module('myapp').controller('indexCtl',['$state','$scope',function ($state,$scope) {
//使用$state.go方法
$scope.gotoHome=function () {
//參數為路由狀態名稱
$state.go('home');
};
}]);
~~~
### 使用ui-sref指令激活路由
【HTML中任意組件都能使用ui-sref指令,但是ui-sref指令只支持點擊事件】
~~~
<!--使用ui-sref指令綁定路由名稱-->
<button ui-sref="home">點擊</button>
<!--任何標簽都可以使用ui-sref指令-->
<a ui-sref="home">HOME頁面</a>
~~~
### 使用$state.go方法
【HTML界面】
~~~
<button ng-click="gotoHome()">使用$state.go方法</button>
~~~
【控制器先依賴$tate對象,然后在使用go方法,方法參數為路由狀態名稱】
~~~
//控制器indexCtl
angular.module('myapp').controller('indexCtl',['$state','$scope',function ($state,$scope) {
//使用$state.go方法
$scope.gotoHome=function () {
//參數為路由狀態名稱
$state.go('home');
};
}]);
~~~
### 使用ui-view指令渲染路由結果
【HTML中使用ui-view指令即可,該指令可以是E也可以是A,指令內容會被路由狀態模板替換】
~~~
<div ui-view>
<h1>這里是路由結果還沒有加載的默認結果嘿嘿</h1>
</div>
~~~
## 路由狀態模板控制器屬性Controller
### 可以為模板指定一個控制器(controller)。警告:如果模板沒有定義,那么控制器不會被實例化。
【路由狀態模板文件homeTpl.html】
~~~
<h1>這里是home</h1>
<p>{{data}}</p>
~~~
【控制器文件app.js】
~~~
angular.module('myapp', ['ui.router']);
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home',{
templateUrl:'homeTpl.html',
//$scope參數綁定作用域數據
controller:function ($scope) {
$scope.data='hzj';
}
});
});
~~~
### 如果在模塊中已經定義了一個控制器,只需要指定控制器的名稱即可
【路由狀態模板文件homeTpl.html】
~~~
<h1>這里是home</h1>
<p>{{data}}</p>
~~~
【控制器文件app.js】
~~~
angular.module('myapp', ['ui.router']);
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home',{
templateUrl:'homeTpl.html',
//$scope參數綁定作用域數據
controller:'Ctrl1'
});
});
//控制器單獨寫
angular.module('myapp').controller('Ctrl1',['$scope',function ($scope) {
$scope.data='hzj';
}]);
~~~
## 路由狀態解決器Resolve屬性
### 路由狀態解決器Resolve可以選擇性的為控制器注入依賴對象
* resolve配置項是一個由key/value構成的對象。
* key – {string}:注入控制器的依賴項名稱。
* value - {string|function}:
* string:一個服務的別名
* function:函數的返回值將作為依賴注入項,如果函數是一個耗時的操作,那么控制器必須等待該函數執行完成(be resolved)才會被實例化。
【app.js】
~~~
angular.module('myapp', ['ui.router']);
//創建一個factory服務
angular.module('myapp').factory('factoryHzj',function () {
return 'factory服務';
});
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home', {
templateUrl: 'homeTpl.html',
//$scope參數綁定作用域數據
controller: 'Ctrl1',
//resolve本身是一個對象,每個對象的key要么是對象、要么是字符串,如果是字符串那么為注入服務
resolve: {
//data屬性利用函數返回了一個對象,該對象有一個屬性為value,值為hzj
data: function () {
//結果對象
var result = {value: 'hzj1111'};
//返回結果對象
return result;
},
//data1屬性利用函數返回一個函數,因為函數也是對象
data1: function () {
var fun=function (a,b) {
return a+b;
};
return fun;
},
//data2屬性利用函數返回一個數組,因為數組也是對象
data2:function () {
var array=[1,2,3,4,5,6];
return array;
},
//data3屬性利用函數的可以任意的使用Angular的服務,這里使用了$location服務
data3:function ($location) {
return $location.absUrl();
},
//直接字符串,代表直接使用服務名稱
data4:'factoryHzj'
},
});
});
//控制器單獨寫
//依賴resolve中的所有data,data1,data2,data3
angular.module('myapp').controller('Ctrl1', function ($scope,data,data1,data2,data3,data4) {
$scope.a = 'hzj';
$scope.b = data.value;
$scope.c = data1(1,2);
$scope.d = data2;
$scope.e = data3;
$scope.f = data4;
});
~~~
【homeTpl.html】
~~~
<h1>這里是home</h1>
<p>{{a}}</p>
<p>{{b}}</p>
<p>{{c}}</p>
<p>{{d}}</p>
<p>{{e}}</p>
<p>{{f}}</p>
~~~
## 路由狀態自定義數據對象data屬性
### 為 $state 對象提供自定義數據
可以給 $state 對象提供自定義數據(建議使用data屬性,以免沖突,因為可以使用任意屬性名稱)
【app.js】
~~~
angular.module('myapp', ['ui.router']);
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home', {
templateUrl: 'homeTpl.html',
//$scope參數綁定作用域數據
controller: 'Ctrl1',
//添加自定義數據,這里是建議使用data名稱,避免與原始屬性沖突
//這里添加了data、data1、data2、data3等三個自定義路由狀態數據
data:'hzj111',
data1:{name:'hzj'},
data2:[1,2,3,4,5,5,6],
data3:function (a,b) {
return a+b;
},
});
});
//控制器單獨寫
//注入$state對象
//然后調用$state對象的current屬性獲取當前路由狀態對象
angular.module('myapp').controller('Ctrl1', function ($scope,$state) {
$scope.a = 'hzj';
$scope.b = $state.current.data;
$scope.c = $state.current.data1.name;
$scope.d = $state.current.data2[2];
$scope.e = $state.current.data3(100,200);
});
~~~
【homeTpl.html】
~~~
<h1>這里是home</h1>
<p>{{a}}</p>
<p>{{b}}</p>
<p>{{c}}</p>
<p>{{d}}</p>
<p>{{e}}</p>
~~~
## 路由狀態自定義數據對象onEnter 和 onExit 屬性
### onEnter和onExit屬性分別稱為當一個狀態變得活躍的和不活躍的時候觸發。回調函數也可以訪問所有解決依賴項。
【app.js】
~~~
angular.module('myapp', ['ui.router']);
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home', {
templateUrl: 'homeTpl.html',
//$scope參數綁定作用域數據
controller: 'Ctrl1',
//當路由狀態激活觸發
onEnter:function () {
console.log('進入');
},
//當路由狀態離開觸發
onExit:function () {
console.log('離開');
}
});
});
//控制器單獨寫
angular.module('myapp').controller('Ctrl1', function ($scope) {
});
~~~
## State Change Events 狀態改變事件
### 路由狀態改變時觸發一系列事件【該事件只會在$rootScope作用域觸發】
* $stateChangeStart - 當模板開始解析之前觸發【注意:使用event.preventDefault()可以阻止模板解析的發生】
* $stateNotFound - v0.3.0 - 在 transition 時通過狀態名查找狀態,當狀態無法找到時發生。該事件在 scope 鏈上廣播,只允許一次處理錯誤的機會。unfoundState將作為參數傳入事件監聽函數,下面例子中可以看到unfoundState的三個屬性。使用 event.preventDefault() 來阻止模板解析,
* $stateChangeSuccess - 當模板解析完成后觸發
* $stateChangeError - 當模板解析過程中發生錯誤時觸發
【app.js】
~~~
//在模塊的run方法中使用$rootScope是一個比較合適的選擇
angular.module('myapp').run(function ($rootScope) {
//當模板開始解析之前觸發
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
//注意:使用event.preventDefault()可以阻止模板解析的發生
// event.preventDefault();
console.log('$stateChangeStart');
});
// $stateNotFound在transition 時通過狀態名查找狀態,當狀態無法找到時發生。
// 該事件在 scope 鏈上廣播,只允許一次處理錯誤的機會。
$rootScope.$on('$stateNotFound', function (event, unfoundState, fromState, fromParams) {
console.log('$stateNotFound');
});
// $stateChangeSuccess - 當模板解析完成后觸發
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
console.log('$stateChangeSuccess');
});
// $stateChangeError - 當模板解析過程中發生錯誤時觸發
$rootScope.$on('$stateChangeError', function (event, toState, toParams, fromState, fromParams, error) {
console.log('$stateChangeError');
});
});
~~~
## View Load Events 視圖加載事件
### 視圖加載的時候觸發一系列事件
$viewContentLoading - 當視圖開始加載,DOM渲染完成之前觸發,該事件將在$scope鏈上廣播此事件。
$viewContentLoaded - 當視圖加載完成,DOM渲染完成之后觸發,視圖所在的$scope發出該事件。
【app.js】
~~~
angular.module('myapp').config(function ($stateProvider, $urlRouterProvider) {
//home是路由名稱,在HTML頁面中可以使用ui-sref綁定
$stateProvider.state('home', {
templateUrl: 'homeTpl.html',
//$scope參數綁定作用域數據
controller: 'Ctrl1',
//當路由狀態激活觸發
onEnter: function () {
console.log('進入');
},
//當路由狀態離開觸發
onExit: function () {
console.log('離開');
}
});
});
//控制器單獨寫
angular.module('myapp').controller('Ctrl1', function ($scope) {
//$viewContentLoading - 當視圖開始加載,DOM渲染完成之前觸發,該事件將在$scope鏈上廣播此事件。
$scope.$on('$viewContentLoading', function (event, viewName) {
console.log('$viewContentLoading..................');
});
//$viewContentLoaded - 當視圖加載完成,DOM渲染完成之后觸發,視圖所在的$scope發出該事件。
$scope.$on('$viewContentLoaded', function (event, viewName) {
console.log('$viewContentLoaded');
});
});
~~~
- Angular簡介
- angular1資料網站
- Angular初級部分
- 打破傳統的前端
- Angular基本組成部分
- Angular環境搭建
- Angular項目測試
- Angular基礎概念
- Angular模塊
- Angular控制器
- Angular指令
- Angular表達式
- Angular視圖
- Angular基礎實戰
- Angular模塊創建和使用
- Angular控制器和模型創建
- scope對象
- 控制器中調度window對象和document對象
- Angular表達式調度過濾器
- Angular中的ng模塊全局方法
- Angular模板應用
- 使用指令復制元素
- 使用指令隱藏顯示元素
- Angular指令ng-if
- ng-src和ng-href
- Angular處理樣式
- Angular作用域事件傳遞
- 表單中的元素
- Angular初學者常見的坑
- 再論雙向綁定
- Angular中級部分
- Angular路由機制
- ui-router管理狀態
- ui-router狀態嵌套和視圖嵌套
- ui-router多個命名的視圖
- ui-router路由控制
- 自定義指令
- 自定義過濾器
- Angular項目目錄結構
- Angular服務
- Angular高級部分
- Angular依賴注入
- README