当前位置:   article > 正文

AngularJS路由之ui-router(二)_angularjs 1.8.2 ui router

angularjs 1.8.2 ui router

基本说明参考:AngularJS路由之ui-router(一)

模块创建时添加模块依赖“ui.router”

var app = angular.module('myApp', ['ui.router']);
后就可以使用一个叫做$state的服务,使用$stateProvider来配置这个服务.
$stateProvider和angualr内置的$routeProvider的用法类似,但是它是通过'状态'来管理路由的.

  • 在整个应用的界面和导航中,状态对应了页面中的一个位置(也就是ui-view)
  • 状态通过controller,template,view等属性,描述了它对应位置的视图展示和行为.
  • 状态之间通常有一些共同点,把这些共同点从模型中分解出来的最好办法就是通过状态继承. 比如父/子状态(又名状态嵌套)
激活一个状态:
调用 $state.go().具体用法以后再讲.
点击一个带有ui-sref属性的a链接.ui-sref属性值就是状态值.具体用法以后再讲.
状态里定义对应url,当页面的url改变成对应状态的url时,就激活这个状态.具体用法以后再讲.
状态的模板:
有几种方法可以定义状态对应的视图模板:
1.定义template属性,属性值为字符串html:
  1. $stateProvider.state('contacts', {
  2. template: '<h1>My Contacts</h1>'
  3. })
2.定义templateUrl属性,属性值一个函数,函数返回值为模板文件对应的url路径:
函数中可以注入$stateParams.$stateParams是url参数组成的键值对对象. 比如这里url里的name就是一个参数,那么,$stateParams就是{name:''}
  1. $stateProvider.state('contacts',{
  2. url:'/contacts/:name',
  3. templateUrl: function($stateParams){
  4. return 'partials/contacts.' + $stateParams.name + '.html'
  5. }
  6. })
3.定义templateProvider属性.属性值是一个函数,函数的返回值为字符串html:
函数中同样可以注入$stateParams
  1. $stateProvider.state('contacts',{
  2. url:'/contacts/:name',
  3. templateProvider: function($stateParams){
  4. return '<h1>'+$stateParams.name+'</h1>'
  5. }
  6. })
状态的控制器和状态控制器的重命名

可以为每个视图模板分配一个控制器. 注意:如果模板没有被定义,那么控制器不会被实例化.
有以下几种方式可以定义控制器:
1.定义controller属性,属性值为模块下定义好的控制器,
在myapp模块下定义了'contact'控制器,然后controller属性就可以直接定义属性值为'contact'

  1. app.config(function ($stateProvider, $urlRouterProvider) {
  2. //注册路由,使用控制器操作(使用外部控制器)
  3. //轻松实现多个视图使用一个控制器
  4. $stateProvider.state('contacts', {
  5. url: '/contacts/:name',
  6. controller: 'contact',
  7. templateProvider: function ($stateParams) {
  8. return '<h1>{{text}},' + $stateParams.name + '</h1>';
  9. }
  10. });
  11. });
  12. app.controller('contact', function ($scope) {
  13. $scope.text = "hi";
  14. });
2.controller属性,属性值就是控制器桉树

  1. app.config(function ($stateProvider, $urlRouterProvider) {
  2. //注册路由,使用控制器操作(注册路由时,指定控制器)
  3. //轻松实现多个视图使用一个控制器
  4. $stateProvider.state('contacts', {
  5. url: '/contacts/:name',
  6. controller: function ($scope) {
  7. $scope.text = 'hi';
  8. },
  9. templateProvider: function ($stateParams) {
  10. return '<h1>{{text}},' + $stateParams.name + '</h1>';
  11. }
  12. });
  13. });
3.定义controller属性,属性为模块下定义好的控制器+‘as con’,并且定义controllerAd属性为'con',然后在作用域中使用con作为controller对象

  1. app.config(function ($stateProvider, $urlRouterProvider) {
  2. //使用as 重命名控制器
  3. $stateProvider.state('contacts', {
  4. url: '/contacts/:name',
  5. controller: 'contact as con',
  6. templateProvider: function ($stateParams) {
  7. return '<h1>{{con.text}},' + $stateParams.name + '</h1>';
  8. },
  9. controllerAs: 'con'
  10. });
  11. });
  12. app.controller('contact', function () {
  13. this.text = "hi";
  14. });
  1. app.config(function ($stateProvider, $urlRouterProvider) {
  2. //使用as 重命名控制器
  3. $stateProvider.state('contacts', {
  4. url: '/contacts/:name',
  5. controller: function () {
  6. this.text = "hi";
  7. },
  8. templateProvider: function ($stateParams) {
  9. return '<h1>{{con.text}},' + $stateParams.name + '</h1>';
  10. },
  11. controllerAs: 'con'
  12. });
  13. });

控制器会根据需要,在对应的作用域被创建的时候实例化. 比如: 当url被改变到和状态匹配的url时,$stateProvider会把对应的模板加载到视图里,然后把控制器绑定到模板的作用域下.

状态的resolve

resolve属性非常重要,它是一个map对象(也就是json对象),它为状态的控制器提供了所需的依赖.这些依赖可以给状态对应的控制器提供所需要的内容或数据.如果resolve属性值中有promise对象,那么它会在控制器被实例化、$stateChangeSuccess事件触发之前被解析并且转换成值.

resolve的属性和属性值应该是这样的:

属性名: 这个名字将会被作为依赖,注入到controller里.
属性值: 字符串|函数     
  • 字符串: 当前模型下既有的服务名       
  • 函数: 函数的返回值会作为依赖,可以被注入到控制器中.如果函数的返回值是一个promise对象,那么它会在控制器被实例化、$stateChangeSuccess事件触发之前被解析并且转换成值.这个值会被作为依赖注入.  
下面这段代码介绍了常见的resolve的六种类型:
  1. var app = angular.module('myApp', ['ui.router']);
  2. app.config(function ($stateProvider, $urlRouterProvider) {
  3. //向controller注入服务
  4. $stateProvider.state('contacts', {
  5. url: '/contacts/:name',
  6. templateUrl: function ($stateParams) {
  7. console.info($stateParams);
  8. return '/template/' + $stateParams.name + '.html'
  9. },
  10. controller: 'ctrl',
  11. resolve: {
  12. //字符串格式,使用一个既有的服务
  13. first: 'aService',
  14. //函数:函数的返回值就是将被注入的服务
  15. send: function () {
  16. return { data: 'second的data ' }
  17. },
  18. //函数:在函数中注入既有的服务
  19. third: function (anotherService, $stateParams) {
  20. var data = anotherService.getName($stateParams.name);
  21. return { data: data }
  22. },
  23. //函数:返回一个promise对象,最终得到的僵尸resolve里的内容
  24. fourth: function ($q, $timeout) {
  25. //限制程序等待,当前view会出现显示阻塞
  26. var defer = $q.defer();
  27. $timeout(function () {
  28. defer.resolve({ data: '我是fourth的data' });
  29. //注意,如果一个state的resolve里的某个promise被拒绝了,那这个state直接无法继续下去了.
  30. //defer.reject({data:'我是fourth的data'})
  31. }, 10000);
  32. return defer.promise;
  33. },
  34. //函数:返回$http返回的promise返回的promise,最终得到的事.then里面return的内容
  35. fifth: function ($http) {
  36. return $http({
  37. method: 'GET',
  38. url: '/contents/getName'
  39. }).then(function (res) {
  40. return { data: res.data }
  41. }, function () {
  42. console.error('请求失败');
  43. });
  44. },
  45. //函数:返回$http返回的promise,最终得到的就是后台返回值
  46. sixth: function ($http) {
  47. return $http({
  48. method: 'GET',
  49. url: '/Contents/name'
  50. });
  51. }
  52. }
  53. });
  54. });
  55. //注册服务
  56. app.factory('aService', function () {
  57. return {
  58. data: 'first的data',
  59. getName: function () {
  60. console.info('aService服务下的getName方法触发');
  61. }
  62. }
  63. });
  64. app.factory('anotherService', function () {
  65. return {
  66. getName: function (data) {
  67. return data.toUpperCase();
  68. }
  69. }
  70. });
  71. //注册controller
  72. app.controller('ctrl', function ($scope, first, send, third, fourth, fifth, sixth) {
  73. first.getName();
  74. console.info(first);
  75. $scope.data1 = first;
  76. $scope.data2 = send;
  77. $scope.data3 = third;
  78. $scope.data4 = fourth;
  79. $scope.data5 = fifth.data;
  80. $scope.data6 = sixth.data;
  81. });
给状态添加自定义数据:

$stateProvider.state('name',{})中的.state第二个参数对象可以添加自定义的属性和值,为了避免冲突,一般使用data属性来为它添加自定义属性.
自定义的属性可以通过$state.current.data来访问到.

  1. app.config(function ($stateProvider, $urlRouterProvider) {
  2. //1.使用路由状态传递参数
  3. //2.路由状态的onEnter和onExit回调处理
  4. $stateProvider.state('contacts', {
  5. url: '/contacts/:name',
  6. templateUrl: function ($stateParams) {
  7. return '/template/' + $stateParams.name + '.html'
  8. },
  9. data: {
  10. data: 1234
  11. },
  12. controller: function ($scope, $state) {
  13. //获取路由状态的参数
  14. // console.info($state.current.data);
  15. $scope.data1 = $state.current.data;
  16. },
  17. resolve: {
  18. title: function () {
  19. return 'contacts';
  20. }
  21. },
  22. onEnter: function (title) {
  23. console.log('进入' + title + '状态');
  24. },
  25. onExit: function (title) {
  26. console.log('推出' + title + '状态');
  27. }
  28. });
  29. });
状态的onEnter和onExit回调:
状态的onEnter属性和onExit属性可以用来定义进入状态和退出状态所执行的回调:
注意,回调函数中可以注入resolve里定义的依赖,比如下面的'title':
状态改变事件:

这些事件都是在$rootScope上触发的.测试证明在$scope中绑定也是管用的
$stateChangeStart: 当状态开始改变时触发, 接受5个参数:

  • event: 事件对象,使用event.preventDefault()可以阻止状态发生改变. 
  • toState: toState是定义.state时传入的第二个参数对象  
  • toParams: toParams就是$stateParams
  • fromState: fromState是上一个状态(就是离开的状态).state时传入的第二个参数对象
  • fromParams: fromParams是上一个状态(就是离开的状态)的$stateParams   
$stateChangeSuccess: 当状态改变结束时触发,可以接受5个参数,5个参数同'$stateChangeStart'的5个参数
$stateNotFound: 当状态没有找到时触发,接受4个参数:
  • event: 事件对象,使用event.preventDefault()可以阻止js继续执行,否则会报错,卡住.
  • unfoundState: 一个对象,这个对象有三个属性:
  • to: 前往的状态名(也就是没有找到的这个状态名)
  • toParams: 前往的状态的参数(在使用ui-sref或者$state.go()的时候可以传入)
  • options: 使用$state.go()的时候传入的第三个参数
  • fromState: 同上
  • fromParams: 同上
$stateChangeError: 当状态改变失败时触发,需要注意,如果在状态的resolve过程中遇到了问题(比如js错误,服务找不到,请求得不到响应等),这些错误不会像传统的那样被抛出,而是会在$stateChangeError里被捕获.它可以接受6个参数
  • event: 事件对象
  • toState: 同上
  • toParams: 同上
  • fromState: 同上
  • fromParams: 同上
  • error: 一个包含了错误信息的对象

视图加载事件:
$viewContentLoading: 当视图开始渲染的时候,$rootScope传播这个事件. 它接受2个参数
event: 事件对象
viewConfig: 包含一个属性:targetView
$viewContentLoaded: 当视图渲染完毕的时候,视图所在的scope传播这个事件.

事件触发执行顺序:
下面来理一下一个状态被激活的过程是怎样的:
1. 触发$stateChangeStart事件,如果使用event.preventDefault(),会阻止状态改变.
如果没有找到对应状态,会触发$stateNotFound事件,然后中断.
2. 触发$viewContentLoading事件.
3. 如果在切换状态的过程中出错(比如resolve出错),触发$stateChangeError事件,无出错跳过此步.
4. 触发上一个状态(若有)的onExit回调事件
5. 触发当前状态的onEnter回调事件
6. 触发$stateChangeSuccess事件
7. 触发$viewContentLoaded事件 


简单实例:

  1. <div class="container" ng-app="myApp">
  2. <h3>AngularJS Home Page Ui-router Test</h3>
  3. <ul class="nav nav-pills">
  4. <li role="presentation" class="active">
  5. <a href="#/contacts/index">首页</a>
  6. </li>
  7. <li role="presentation">
  8. <a href="#/contacts/list">列表页</a>
  9. </li>
  10. <li role="presentation">
  11. <a href="#/contacts/stop">被拒绝</a>
  12. </li>
  13. <li role="presentation">
  14. <a ui-sref="lalala({a:1,b:2})"></a>
  15. </li>
  16. </ul>
  17. <div data-ui-view="" loading>点击连接后内容被加载咋爱这里</div>
  18. </div>
js:

  1. var app = angular.module('myApp', ['ui.router']);
  2. app.config(function ($stateProvider, $urlRouterProvider) {
  3. //1.使用路由状态传递参数
  4. //2.路由状态的onEnter和onExit回调处理
  5. $stateProvider.state('contacts', {
  6. url: '/contacts/:name',
  7. templateUrl: function ($stateParams) {
  8. return '/template/' + $stateParams.name + '.html'
  9. },
  10. data: {
  11. data: 1234
  12. },
  13. controller: function ($scope, $state) {
  14. //获取路由状态的参数
  15. // console.info($state.current.data);
  16. $scope.data1 = $state.current.data;
  17. }
  18. });
  19. });
  20. //注册指令
  21. app.directive('loading', function ($rootScope) {
  22. return {
  23. restrict: 'EA',
  24. link: function (scope, iEle, iAttrs, ctrl) {
  25. console.log(scope == $rootScope);
  26. //状态事件
  27. scope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
  28. console.log('状态开始改变');
  29. /*toState是定义.state时传入的第二个参数对象*/
  30. console.info(toState);
  31. /*toParams就是$stateParams*/
  32. console.info(toParams);
  33. /*fromState是上一个状态.state时传入的第二个参数对象*/
  34. console.info(fromState);
  35. /*fromParams就是上一个状态的$stateParams*/
  36. console.log(fromParams);
  37. if (toParams.name == 'stop') {
  38. alert('阻止页面');
  39. event.preventDefault();
  40. }
  41. });
  42. scope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
  43. console.log('状态改变结束');
  44. /*参数同上*/
  45. });
  46. scope.$on('$stateNotFound', function (event, unfoundState, fromState, fromParams) {
  47. console.log('没有找到对应的状态');
  48. /*unfoundState包含了三个属性:*/
  49. /*1.to:前往的状态名(也就是没有找到的这个状态名)
  50. * 2.toParams:前往的状态的参数(在使用ui-sref或者$state.go()的时候可以传入,这个例子里就是{a:1,b:2})
  51. * 3.options:使用$state.go()的时候传入的第三个参数.
  52. * */
  53. /*最后两个参数同上*/
  54. console.log(unfoundState);
  55. //如果不写这句,那么接下来就会报错,卡住js进程了.
  56. event.preventDefault()
  57. });
  58. scope.$on('$stateChangeError', function (event, toState, toParams, fromState, fromParams, error) {
  59. console.log('切换状态出错');
  60. /*error是一个包含了错误信息的对象*/
  61. console.info(error);
  62. });
  63. //视图事件
  64. scope.$on('$viewContentLoading', function (event, viewConfig) {
  65. console.log('视图开始加载');
  66. });
  67. scope.$on('$viewContentLoaded', function (event) {
  68. console.log('视图渲染完毕');
  69. });
  70. }
  71. }
  72. });




博文内容来源:http://www.cnblogs.com/liulangmao/p/4155015.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/1009306
推荐阅读
相关标签
  

闽ICP备14008679号