AngularJS路由系列(4)-- UI-Router的$state服务、路由事件、获取路由参数

本系列探寻AngularJS的路由机制,在WebStorm下开发。主要包括:

UI-Router的$state服务
UI-Router的路由事件
UI-Router获取路由参数


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的$state服务

方法:
● go()  
● reload()
● get()

属性:
● current
● params

事件
● $stateChangeError
● $stateChangeStart
● $stateChangeSuccess
● $stateNotFound


■ index.html, 使用ui-sref

bootstrap.cerulean.min.css
toastr.min.css

<!--Angular-->
angular.min.js
angular-ui-router.min.js

<!--Application-->
app.js

<!--Services-->
dataServices.js
notifier.js

<!--Filters-->
activityMonthFilter.js

<!--Controls-->
HomeController.js
AllSchoolsController.js
AllClassroomsController.js
AllActivityiesController.js
ClassroomController.js
ClassroomSummaryController.js
ClassroomMessageController.js


<body ng-app="app">
    <a ui-sref="home">School Buddy</a>
    <a ui-sref="schools">Schools</a>
    <a ui-sref="classrooms">Classrooms</a>
    <a ui-sref="activities">Activities</a>
    
    <div ui-view></div>
</body>

■ HomeController.js

(function(){
    angular.module('app')
        .controller('HomeController', ['dataService', 'notifier', '$state','$log', HomeController]);
        
    function HomeController(dataService, notifier, $state, $log){
        var vm = this;
        
        vm.message = 'Welcome to School Buddy';
        
        //使用$state服务
        vm.refresh = function(){
            $log.debug($state.current);
            $state.reload();
        }
        
        dataService.getAllSchools()
            .then(function(schools){
                vm.allSchools = schools;
                vm.schoolCount = schools.length;
            })
            .catch(showError);
            
        dataService.getAllClassrooms()
            .then(function(classrooms){
                vm.allClassrooms = classrooms;
                vm.classroomCount = classrooms.length;
            })
            .catch(showError);
        
        ...
    }
}());

■ home.html

{{home.message}}
{{home.schoolCount}}
{{home.classroomCount}}
{{home.activityCount}}

<button ng-click="home.refresh()">刷新</button>

点击"刷新"按钮。

可见,$state.reload()方法只刷新路由部分,与浏览器的刷新按钮功能是不一样的。

控制台方面,$state.current代表的当前如下:

UI-Router的路由事件



■ app.js, 给$rootScope添加有关路由的事件

(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',
                resolve: {
                    promise: function(){
                        throw 'error activating classrooms';
                    }
                }
            })
            .state('activities', {
                url: '/activities',
                controller: 'AllActivitiesController',
                controllerAs: 'activities',
                templateUrl: '/app/templates/allActivities.html'
            })
    }]);
    
    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);
        });
    }]);
}());

■ index.html, 故意制造一个404错误

bootstrap.cerulean.min.css
toastr.min.css

<!--Angular-->
angular.min.js
angular-ui-router.min.js

<!--Application-->
app.js

<!--Services-->
dataServices.js
notifier.js

<!--Filters-->
activityMonthFilter.js

<!--Controls-->
HomeController.js
AllSchoolsController.js
AllClassroomsController.js
AllActivityiesController.js
ClassroomController.js
ClassroomSummaryController.js
ClassroomMessageController.js


<body ng-app="app">
    <a ui-sref="home">School Buddy</a>
    <a ui-sref="schools">Schools</a>
    <a ui-sref="classrooms">Classrooms</a>
    <a ui-sref="activitiesAAA">Activities</a>
    
    <div ui-view></div>
</body>

在<a ui-sref="activitiesAAA">Activities</a>这里制造了一个404错误。

点击首页的"刷新"按钮。



点击Schools



点击Classroom故意抛出的异常


点击Activities故意抛出404异常。


UI-Router获取路由参数



UI-Router为我们提供了$stateParams服务。

.state('classrooms',{
    url: '/classrooms/:id'
})
.state('classrooms',{
    url: '/classrooms/{id}'
})
.state('activities',{
    url: '/activities',
    params: {
        id: { value: 42}
    }
})

localhost:3000/#/classrooms/3

function ClassroomController($stateParams){
    var classroomID = $stateParams.id;
}


■ 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'
            })
    }]);
    
    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;
        
        dataService.getClassroom($stateParams.id)
            .then(function(classroom){
                vm.currentClassroom = classroom;
            })
            .catch(showError);
            
        function showError(message){
            notifier.error(message);
        }
        
    }
}());

■ allClassrooms.html

<tr ng-repeat="classroom in classrooms.allClassrooms">
    <td><a href="#/classrooms/{{classroom.id}}/details">{{classroom.name}}</a></td>
    <td>{{classroom.school.name}}</td>
    <td><a ui-sref="classroom_summary({id: classroom.id})">{{classroom.teacher}}</a></td>
</tr>

在浏览器中输入:localhost:3000/#/classrooms/1

■ 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}/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);
        });
    }]);
}());

■ ClassroomController.js, 接受更多的路由参数

(function(){
    angular.module('app')
        .controller('ClassroomController',['dataService', 'notifier', '$stateParams', ClassroomController]);
        
    function ClassroomController(dataService, notifier, $stateParams){
        var vm = this;
        
        vm.month = $stateParams.month;
        
        
        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);
        }
        
    }
}());

■ AllActivitiesController.js

(function(){
    angular.module('app')
        .controller('AllActivitiesController',['dataService', 'notifier', '$state', AllActivitiesController]);
        
    function AllActivitiesController(dataService, notifier, $state){
        var vm = this;
        
        
        vm.selectedMonth = 1;
        
        vm.search = function(){
            $state.go('classroom_detail',{id: vm.selectedClassroom.id, month: vm.seletedMonth});
        }
        
        dataServie.getAllClassrooms()
            .then(function(classrooms){
                vm.allClassrooms = classrooms;
                vm.selectedClassroom = classrooms[0];
            })
            .catch(showError);
        
        dataService.getAllActivities()
            .then(function(activities){
                vm.allActivities = activities;
            })
            .catch(showError);
            
        function showError(message){
            notifier.error(message);
        }
    }
}());


浏览器中输入:localhost:3000/#/classrooms/1/detail/12

未完待续~~

原文地址:https://www.cnblogs.com/darrenji/p/4982480.html