前言
我們知道默認的路由提供(Route Provider)在復雜的應用程序中是不太適合應用場景,它存在諸多限制,所以在Angular 1.2之后此時我們不得不將路由提供作為一個單獨的模塊當我們需要使用時即ngRoute,但是該ngRoute使用起來還是不夠靈活,AngularJS團隊很快意識到了這點,於是提出了ui.router作為ngRoute的完美替代品。
話題
此節我們要討論關於Route的高級,也就是深入探討AngularUi Router中的比較高級的內容,關於ui.router有如下強大特點:
(1)嵌套狀態和嵌套視圖。
(2)多個命名視圖(由一個視圖到另外一個視圖通過引用視圖的名稱)。
(3)嵌套解析(一個解析等待另外一個解析完畢)。
(4)ui.sref指令(綁定超鏈接,並自動生成)。
......
對於本節我們則要講述的是路由的resolve,在ngRoute中也存在resolve,ui.router中的resolve相比較更加強大,於是對於ngRoute中的Resolve未做過多探討,有興趣的童鞋可以自行去學習,那resolve到底是做什么的?它可以在一個路由中提前加載數據,接着這個resolve中的屬性會被注入到此路由的控制器中,ui.router中的reolve應該是該路由模塊中最大的特性。當resolve中的全部屬性被解析完畢時,resolve才會執行,意味着是延遲執行。下面我們來一步一步看看resolve。
高級路由之resolve(返回字符串)
通過在resolve中通過函數返回一個字符串,此時會立即被解析。我們來看看。
UI
<html> <head> <meta charset="UTF-8"> <title></title> <script type="text/javascript" src="../Scripts/angular.min.js"></script> <script src="../ui-router/angular-ui-router.min.js"></script> <script src="app.js"></script> </head> <body ng-app="app"> <div ui-view></div> </body> </html>
app.js
angular.module("app",["ui.router"]) .config(config); function config($stateProvider,$urlRouterProvider){ $urlRouterProvider.otherwise("/resolve"); $stateProvider.state("resolve",{ url:"/resolve", templateUrl:"resolve.html", resolve: { cnblogs:function(){ return "xpy0928"; } }, controller: function($scope, cnblogs){ $scope.loadData = cnblogs; } }); }
我們接着在視圖resolve.html中顯示綁定的數據 {{loadData}} 結果毫無疑問顯示xpy0928。
上述我們是在視圖內部定義的控制器從而綁定數據,如果我們的Application足夠大,此時路由勢必會膨脹,在這種情況下,我們還是單獨定義控制器並綁定數據,如下:
function config($stateProvider,$urlRouterProvider){ $urlRouterProvider.otherwise("/resolve"); $stateProvider.state("resolve",{ url:"/resolve", templateUrl:"resolve.html", controller:"resolveVM", resolve: { cnblogs:function(){ return "xpy0928"; } } }); } angular.module("app").controller("resolveVM",function($scope,cnblogs){ $scope.loadData = cnblogs; });
同時我們也應該注意,當我們沒有宿主運行時,對於有些瀏覽器可能會出現違背了跨域,在AnuglarJS中啟動跨域,可以進行如下操作:
$httpProvider.defaults.useXDomain = true; delete $httpProvider.defaults.headers.common['X-Requested-With'];
上述對於簡單使用resolve給出了一個基本的例子,我們再往下面看看。
高級Route之resolve(返回promise【推薦】)
我們首先看看一個最簡單返回promise的例子。我們只需在上述app.js中的resolve進行如下修改:
resolve: { promiseObj: function($http){ return $http({method: 'GET', url: ''}); },
貌似還是不太樂觀,下面我們詳細介紹下,一般對於resolve無非就是通過resource即http請求來返回數據當然或者通過服務來獲取數據。上述是我們簡單的返回一個promise,我們完全可以自定義一個promise。將resolve修改如下:
resolve: { delayedData: function($q, $timeout) { var deferred = $q.defer(); $timeout(function() { var myData = {message: 'hello,everyone!xpy0928 from cnblogs'}; deferred.resolve(myData); }, 1000); return deferred.promise; } }
接下來我們來綁定數據:
angular.module("app").controller("resolveVM",function($scope,delayedData){ $scope.loadData = delayedData; });
誒,貌似沒圖,還是演示下:
上述有說過我們利用resolve無非根據http獲取數據,在AngularJS中利用ngResource來實現(推薦前面的替代品,這里只是作為演示用)。
resolve a resource's promise
我們如下修改resolve:
resolve: { userData: function(userList) { var list = userList.query(); return list.$promise; } }
創建獲取用戶列表服務:
angular.module("app").factory('userList', ['$resource', function ($resource) { return $resource('http://localhost:52005/api/cnblogs/getUserlist'); }]); angular.module("app").controller("resolveVM",function($scope,userData){ $scope.loadData = userData; });
我們看下效果:
resolve multiple resource's promise
上述只是利用resolve解析一個promise,若我們要在路由或者狀態發生改變之前解析多個promise,此時我們該如何做?我們此時利用$q.all開完成,我們來看如下代碼:
resolve: { userData: function($q,userList,blogList) { var list = userList.query(); var bloglist = blogList.query(); return $q.all([list.$promise,blogList.$promise]) .then(function(){ }) } }
通過resource獲取數據:
angular.module("app").factory('userList', ['$resource', function ($resource) { return $resource('http://localhost:52005/api/cnblogs/getUserlist'); }]); angular.module("app").factory('blogList', ['$resource', function ($resource) { return $resource('http://localhost:52005/api/cnblogs/getBloglist'); }]);
如上,就是這么簡單。
總結
本節我們講了路由中比較高級的知識resolve,建議在實際開發中利用ui.router來完成而非ngRouter中的resolve,同時本節也涉及到了$q/promise,本節未進行詳細闡述,下節我們我們仔細講講$q或者其他知識。
補充
本打算再寫一篇關於promise的文章,搜到一篇寫的非常好的文章,那就不再講述了鏈接如下:
AngularJS 中的Promise和設計模式: http://my.oschina.net/ilivebox/blog/293771?p=1