本系列探寻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
未完待续~~