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');
    }
})

 

 

 

未完待续~~

 

posted @ 2015-11-20 22:38  Darren Ji  阅读(7631)  评论(0编辑  收藏  举报

我的公众号:新语新世界,欢迎关注。