AngularJS路由系列(5)-- UI-Router的路由约束、Resolve属性、路由附加数据、路由进入退出事件
本系列探寻AngularJS的路由机制,在WebStorm下开发。主要包括:
● UI-Router约束路由参数
● UI-Router的Resolve属性
● UI-Router给路由附加数据
● UI-Router的onEnter和onExit事件
AngularJS路由系列包括:
1、AngularJS路由系列(1)--基本路由配置
2、AngularJS路由系列(2)--刷新、查看路由,路由事件和URL格式,获取路由参数,路由的Resolve
3、AngularJS路由系列(3)-- UI-Router初体验
4、AngularJS路由系列(4)-- UI-Router的$state服务、路由事件、获取路由参数
5、AngularJS路由系列(5)-- UI-Router的路由约束、Resolve属性、路由附加数据、路由进入退出事件
6、AngularJS路由系列(6)-- UI-Router的嵌套State
项目文件结构
node_modules/
public/
.....app/
..........bower_components/
...............toastr/
....................toastr.min.css
....................toastr.min.js
...............jquery/
....................dist/
.........................jquery.min.js
...............angular/
....................angular.min.js
...............angular-ui-router/
....................release/
.........................angular-ui-router.min.js
...............angular-route/
.........................angular-route.min.js
..........controllers/
...............HomeController.js
...............AllSchoolsController.js
...............AllClassroomsController.js
...............AllActivityiesController.js
...............ClassroomController.js
...............ClassroomSummaryController.js
...............ClassroomMessageController.js
..........css/
...............bootstrap.cerulean.min.css
..........filters/
...............activityMonthFilter.js
..........services/
...............dataServices.js
...............notifier.js
..........templates/
...............home.html
...............allSchools.html
...............allClassrooms.html
...............allActivities.html
...............classroom.html
...............classroomDetail.html
...............classroom_parent.html
..........app.js
.....index.html
.....favicon.ico
server/
.....data/
.....routes/
.....views/
.....helpers.js
package.json
server.js
UI-Router约束路由参数
■ app.js, 约束参数
(function(){ var app = angular.module(‘app‘,[‘ui.router‘]); app.config([‘$logProvider‘, ‘$stateProvider‘, function($logProvider, $stateProvider){ $logProvider.debugEnabled(true); $stateProvider .state(‘home‘,{ url: ‘/‘, templateUrl: ‘/app/templates/home.html‘, controller: ‘HomeController‘, //也可以写成HomeController as home controllerAs: ‘home‘ }) .state(‘schools‘,{ url: ‘/schools‘, controller: ‘AllSchoolController‘, controllerAs: ‘schools‘, templateUrl: ‘/app/templates/allSchools.thml‘ }) .state(‘classrooms‘,{ url:‘/classrooms‘, controller: ‘AllClassroomsController‘, controllerAs: ‘classrooms‘, templateUrl: ‘/app/tempates/allClassrooms.html‘ }) .state(‘activities‘, { url: ‘/activities‘, controller: ‘AllActivitiesController‘, controllerAs: ‘activities‘, templateUrl: ‘/app/templates/allActivities.html‘ }) .state(‘classroom_summary‘, { url: ‘/classrooms/:id‘, templateUrl: ‘/app/templates/classroom.html‘, controller: ‘ClassroomController‘, controllerAs: ‘classroom‘ }) .state(‘classroom_detail‘,{ url: ‘/classrooms/{id: [0-9]}/detail/{month}‘, templateUrl: ‘/app/templates/classroomDetail.html‘, controller: ‘ClassroomController‘, controllerAs: ‘classroom‘ }) }]); app.run([‘$rootScope‘, ‘$log‘, function($rootScope, $log){ $rootScope.$on(‘$stateChangeSuccess‘, function(event, toState, toParams, fromState, fromParams){ $log.debug(‘successfully changed states‘) ; $log.debug(‘event‘, event); $log.debug(‘toState‘, toState); $log.debug(‘toParams‘, toParams); $log.debug(‘fromState‘, fromState); $log.debug(‘fromParams‘, fromParams); }); $rootScope.$on(‘$stateNotFound‘, function(event, unfoundState, fromState, fromParams){ $log.error(‘The request state was not found: ‘ + unfoundState); }); $rootScope.$on(‘$stateChangeError‘, function(event, toState, toParams, fromState, fromParams, error){ $log.error(‘An error occurred while changing states: ‘ + error); $log.debug(‘event‘, event); $log.debug(‘toState‘, toState); $log.debug(‘toParams‘, toParams); $log.debug(‘fromState‘, fromState); $log.debug(‘fromParams‘, fromParams); }); }]); }());
url: ‘/classrooms/{id: [0-9]}/detail/{month}‘这个就对id这个路由参数进行了约束。
■ app.js, 路由参数不符合约束的解决办法
UI-Router为我们提供了$urlRouteProvider服务。
(function(){ var app = angular.module(‘app‘,[‘ui.router‘]); app.config([‘$logProvider‘, ‘$stateProvider‘, ‘$urlRouteProvider‘, function($logProvider, $stateProvider, $urlRouteProvider){ $logProvider.debugEnabled(true); //解决路由异常的办法在这里 $urlRouteProvider.otherwise(‘/‘); $stateProvider .state(‘home‘,{ url: ‘/‘, templateUrl: ‘/app/templates/home.html‘, controller: ‘HomeController‘, //也可以写成HomeController as home controllerAs: ‘home‘ }) .state(‘schools‘,{ url: ‘/schools‘, controller: ‘AllSchoolController‘, controllerAs: ‘schools‘, templateUrl: ‘/app/templates/allSchools.thml‘ }) .state(‘classrooms‘,{ url:‘/classrooms‘, controller: ‘AllClassroomsController‘, controllerAs: ‘classrooms‘, templateUrl: ‘/app/tempates/allClassrooms.html‘ }) .state(‘activities‘, { url: ‘/activities‘, controller: ‘AllActivitiesController‘, controllerAs: ‘activities‘, templateUrl: ‘/app/templates/allActivities.html‘ }) .state(‘classroom_summary‘, { url: ‘/classrooms/:id‘, templateUrl: ‘/app/templates/classroom.html‘, controller: ‘ClassroomController‘, controllerAs: ‘classroom‘ }) .state(‘classroom_detail‘,{ url: ‘/classrooms/{id: [0-9]}/detail/{month}‘, templateUrl: ‘/app/templates/classroomDetail.html‘, controller: ‘ClassroomController‘, controllerAs: ‘classroom‘ }) }]); app.run([‘$rootScope‘, ‘$log‘, function($rootScope, $log){ $rootScope.$on(‘$stateChangeSuccess‘, function(event, toState, toParams, fromState, fromParams){ $log.debug(‘successfully changed states‘) ; $log.debug(‘event‘, event); $log.debug(‘toState‘, toState); $log.debug(‘toParams‘, toParams); $log.debug(‘fromState‘, fromState); $log.debug(‘fromParams‘, fromParams); }); $rootScope.$on(‘$stateNotFound‘, function(event, unfoundState, fromState, fromParams){ $log.error(‘The request state was not found: ‘ + unfoundState); }); $rootScope.$on(‘$stateChangeError‘, function(event, toState, toParams, fromState, fromParams, error){ $log.error(‘An error occurred while changing states: ‘ + error); $log.debug(‘event‘, event); $log.debug(‘toState‘, toState); $log.debug(‘toParams‘, toParams); $log.debug(‘fromState‘, fromState); $log.debug(‘fromParams‘, fromParams); }); }]); }());
■ UI-Router的params属性设置路由参数
(function(){ var app = angular.module(‘app‘,[‘ui.router‘]); app.config([‘$logProvider‘, ‘$stateProvider‘, ‘$urlRouteProvider‘, function($logProvider, $stateProvider, $urlRouteProvider){ $logProvider.debugEnabled(true); //解决路由异常的办法在这里 $urlRouteProvider.otherwise(‘/‘); $stateProvider .state(‘home‘,{ url: ‘/‘, templateUrl: ‘/app/templates/home.html‘, controller: ‘HomeController‘, //也可以写成HomeController as home controllerAs: ‘home‘ }) .state(‘schools‘,{ url: ‘/schools‘, controller: ‘AllSchoolController‘, controllerAs: ‘schools‘, templateUrl: ‘/app/templates/allSchools.thml‘ }) .state(‘classrooms‘,{ url:‘/classrooms‘, controller: ‘AllClassroomsController‘, controllerAs: ‘classrooms‘, templateUrl: ‘/app/tempates/allClassrooms.html‘ }) .state(‘activities‘, { url: ‘/activities‘, controller: ‘AllActivitiesController‘, controllerAs: ‘activities‘, templateUrl: ‘/app/templates/allActivities.html‘ }) .state(‘classroom_summary‘, { url: ‘/classrooms/:id‘, templateUrl: ‘/app/templates/classroom.html‘, controller: ‘ClassroomController‘, controllerAs: ‘classroom‘ }) .state(‘classroom_detail‘,{ url: ‘/classrooms/{id: [0-9]}/detail/{month}‘, templateUrl: ‘/app/templates/classroomDetail.html‘, controller: ‘ClassroomController‘, controllerAs: ‘classroom‘, params: { classroomMessage: { value: ‘Learning is fun!‘} } }) }]); app.run([‘$rootScope‘, ‘$log‘, function($rootScope, $log){ $rootScope.$on(‘$stateChangeSuccess‘, function(event, toState, toParams, fromState, fromParams){ $log.debug(‘successfully changed states‘) ; $log.debug(‘event‘, event); $log.debug(‘toState‘, toState); $log.debug(‘toParams‘, toParams); $log.debug(‘fromState‘, fromState); $log.debug(‘fromParams‘, fromParams); }); $rootScope.$on(‘$stateNotFound‘, function(event, unfoundState, fromState, fromParams){ $log.error(‘The request state was not found: ‘ + unfoundState); }); $rootScope.$on(‘$stateChangeError‘, function(event, toState, toParams, fromState, fromParams, error){ $log.error(‘An error occurred while changing states: ‘ + error); $log.debug(‘event‘, event); $log.debug(‘toState‘, toState); $log.debug(‘toParams‘, toParams); $log.debug(‘fromState‘, fromState); $log.debug(‘fromParams‘, fromParams); }); }]); }());
■ ClassroomController.js, 接受更多的路由参数
(function(){ angular.module(‘app‘) .controller(‘ClassroomController‘,[‘dataService‘, ‘notifier‘, ‘$stateParams‘, ClassroomController]); function ClassroomController(dataService, notifier, $stateParams){ var vm = this; vm.month = $stateParams.month; //接受param设置的参数 vm.message = $stateParams.classroomMessage; dataService.getClassroom($stateParams.id) .then(function(classroom){ vm.currentClassroom = classroom; if($stateParams.month){ if(classroom.activities.length > 0){ vm.timePeriod = dataService.getMonthName($stateParams.month); } else { vm.timePeriod = ‘No activities this month‘; } } else{ vm.timePeriod = ‘All activities‘; } }) .catch(showError); function showError(message){ notifier.error(message); } } }());
■ classroomDetal.html
{{classroom.message}}
UI-Router的Resolve属性
■ resolve 属性
.state(‘activities‘,{ url: ‘/activities‘, controller: ‘AllAcivitiesController‘, controllerAs: ‘activities‘, templateUrl: ‘/app/templates/allActivities.html‘, resolve: { activities: function(dataService){ return dataService.getAllActiviites(); } } })
● 可以被注入到controller中去
● 返回一个object对象,对象的属性自定义,属性值是一个返回promise的函数
● promises必须被resolve,在变化发生之前
■ app.js, 添加resolve属性
.state(‘activities‘,{ url: ‘/activities‘, controller: ‘AlLActivitiesController‘, controllerAs: ‘activities‘, templateUrl: ‘/app/templates/allActivities.html‘, resolve: { activities: function(dataService){ return dataService.getAllActivites(); } } })
■ AllActivitiesController.js,从resolve中获取数据
(function(){ angular.module(‘app‘) .controller(‘AllActivitiesController‘,[‘dataService‘,‘notifier‘,‘$state‘,‘activites‘, AllActivitiesController]); function AllActivitiesController(dataService, notifier, $state, activities){ var vm = this; vm.selectedMonth = 1; vm.allActivities = activities; vm.search = function(){ $state.go(‘classroom_detail‘,{id:vm.selectedClassroom.id, month: vm.selectedMonth}); } dataService.getAllClassrooms() .then(function(classroom){ vm.allClassrooms = classrooms; vm.selectedClassroom = classrooms[0]; }) .catch(showError); function showError(message){ notifier.error(message); } } }());
当点击Activites的时候,数据已经在controller,不需要重新获取,大大减少了页面加载时间。
UI-Router给路由附加数据
■ 给states附加数据
.state(‘activities‘,{ url: ‘/activities‘, controller: ‘AllActivitesController‘, templateUlr: ‘/app/templates/allActivities.html‘, data: { name: ‘MyActivity‘, desc: ‘Fun!‘ } })
● data中定义的属性是任意的
● 能被子state继承
■ app.js, 添加附加数据
.state(‘activities‘,{ url: ‘/activities‘, controller: ‘AlLActivitiesController‘, controllerAs: ‘activities‘, templateUrl: ‘/app/templates/allActivities.html‘, resolve: { activities: function(dataService){ return dataService.getAllActivites(); } }, data: { name: ‘My Activity‘, desc: ‘Func!‘ }, foo: { myFoo: ‘bar‘ } })
■ AllActivitiesController.js,从resolve中获取数据
(function(){ angular.module(‘app‘) .controller(‘AllActivitiesController‘,[‘dataService‘,‘notifier‘,‘$state‘,‘activites‘,‘$log‘, AllActivitiesController]); function AllActivitiesController(dataService, notifier, $state, activities, $log){ var vm = this; vm.selectedMonth = 1; vm.allActivities = activities; $log.debug($state.current.data); $log.debug($state.current.foo); vm.search = function(){ $state.go(‘classroom_detail‘,{id:vm.selectedClassroom.id, month: vm.selectedMonth}); } dataService.getAllClassrooms() .then(function(classroom){ vm.allClassrooms = classrooms; vm.selectedClassroom = classrooms[0]; }) .catch(showError); function showError(message){ notifier.error(message); } } }());
UI-Router的onEnter和onExit事件
.state(‘classroom‘,{ url:‘/clsssrooms‘, controller:‘AllClssroomsController‘, controllerAs: ‘classrooms‘, templateUrl: ‘/app/tempaltes/allClassrooms.html‘, onEnter: function($log){ $log.debug(‘Entering the classrooms state‘); }, onExit: function($log){ $log.debug(‘Existing the classrooms state‘); } })
未完待续~~