本文共 11303 字,大约阅读时间需要 37 分钟。
基本说明参考:
模块创建时添加模块依赖“ui.router”
var app = angular.module('myApp', ['ui.router']);后就可以使用一个叫做$state的服务,使用$stateProvider来配置这个服务. $stateProvider和angualr内置的$routeProvider的用法类似,但是它是通过'状态'来管理路由的.
$stateProvider.state('contacts', {template: '2.定义templateUrl属性,属性值一个函数,函数返回值为模板文件对应的url路径: 函数中可以注入$stateParams.$stateParams是url参数组成的键值对对象. 比如这里url里的name就是一个参数,那么,$stateParams就是{name:''}My Contacts
'})
$stateProvider.state('contacts',{url:'/contacts/:name',templateUrl: function($stateParams){return 'partials/contacts.' + $stateParams.name + '.html'}})3.定义templateProvider属性.属性值是一个函数,函数的返回值为字符串html: 函数中同样可以注入$stateParams
$stateProvider.state('contacts',{url:'/contacts/:name',templateProvider: function($stateParams){return '状态的控制器和状态控制器的重命名'+$stateParams.name+'
'}})
可以为每个视图模板分配一个控制器. 注意:如果模板没有被定义,那么控制器不会被实例化.
有以下几种方式可以定义控制器: 1.定义controller属性,属性值为模块下定义好的控制器, 在myapp模块下定义了'contact'控制器,然后controller属性就可以直接定义属性值为'contact'app.config(function ($stateProvider, $urlRouterProvider) { //注册路由,使用控制器操作(使用外部控制器) //轻松实现多个视图使用一个控制器 $stateProvider.state('contacts', { url: '/contacts/:name', controller: 'contact', templateProvider: function ($stateParams) { return '2.controller属性,属性值就是控制器桉树{ {text}},' + $stateParams.name + '
'; } });});app.controller('contact', function ($scope) { $scope.text = "hi";});
app.config(function ($stateProvider, $urlRouterProvider) { //注册路由,使用控制器操作(注册路由时,指定控制器) //轻松实现多个视图使用一个控制器 $stateProvider.state('contacts', { url: '/contacts/:name', controller: function ($scope) { $scope.text = 'hi'; }, templateProvider: function ($stateParams) { return '3.定义controller属性,属性为模块下定义好的控制器+‘as con’,并且定义controllerAd属性为'con',然后在作用域中使用con作为controller对象{ {text}},' + $stateParams.name + '
'; } });});
app.config(function ($stateProvider, $urlRouterProvider) { //使用as 重命名控制器 $stateProvider.state('contacts', { url: '/contacts/:name', controller: 'contact as con', templateProvider: function ($stateParams) { return '{ {con.text}},' + $stateParams.name + '
'; }, controllerAs: 'con' });});app.controller('contact', function () { this.text = "hi";});
app.config(function ($stateProvider, $urlRouterProvider) { //使用as 重命名控制器 $stateProvider.state('contacts', { url: '/contacts/:name', controller: function () { this.text = "hi"; }, templateProvider: function ($stateParams) { return '{ {con.text}},' + $stateParams.name + '
'; }, controllerAs: 'con' });});
控制器会根据需要,在对应的作用域被创建的时候实例化. 比如: 当url被改变到和状态匹配的url时,$stateProvider会把对应的模板加载到视图里,然后把控制器绑定到模板的作用域下.
状态的resolve resolve属性非常重要,它是一个map对象(也就是json对象),它为状态的控制器提供了所需的依赖.这些依赖可以给状态对应的控制器提供所需要的内容或数据.如果resolve属性值中有promise对象,那么它会在控制器被实例化、$stateChangeSuccess事件触发之前被解析并且转换成值. resolve的属性和属性值应该是这样的: 属性名: 这个名字将会被作为依赖,注入到controller里. 属性值: 字符串|函数var app = angular.module('myApp', ['ui.router']);app.config(function ($stateProvider, $urlRouterProvider) { //向controller注入服务 $stateProvider.state('contacts', { url: '/contacts/:name', templateUrl: function ($stateParams) { console.info($stateParams); return '/template/' + $stateParams.name + '.html' }, controller: 'ctrl', resolve: { //字符串格式,使用一个既有的服务 first: 'aService', //函数:函数的返回值就是将被注入的服务 send: function () { return { data: 'second的data ' } }, //函数:在函数中注入既有的服务 third: function (anotherService, $stateParams) { var data = anotherService.getName($stateParams.name); return { data: data } }, //函数:返回一个promise对象,最终得到的僵尸resolve里的内容 fourth: function ($q, $timeout) { //限制程序等待,当前view会出现显示阻塞 var defer = $q.defer(); $timeout(function () { defer.resolve({ data: '我是fourth的data' }); //注意,如果一个state的resolve里的某个promise被拒绝了,那这个state直接无法继续下去了. //defer.reject({data:'我是fourth的data'}) }, 10000); return defer.promise; }, //函数:返回$http返回的promise返回的promise,最终得到的事.then里面return的内容 fifth: function ($http) { return $http({ method: 'GET', url: '/contents/getName' }).then(function (res) { return { data: res.data } }, function () { console.error('请求失败'); }); }, //函数:返回$http返回的promise,最终得到的就是后台返回值 sixth: function ($http) { return $http({ method: 'GET', url: '/Contents/name' }); } } });});//注册服务app.factory('aService', function () { return { data: 'first的data', getName: function () { console.info('aService服务下的getName方法触发'); } }});app.factory('anotherService', function () { return { getName: function (data) { return data.toUpperCase(); } }});//注册controllerapp.controller('ctrl', function ($scope, first, send, third, fourth, fifth, sixth) { first.getName(); console.info(first); $scope.data1 = first; $scope.data2 = send; $scope.data3 = third; $scope.data4 = fourth; $scope.data5 = fifth.data; $scope.data6 = sixth.data;});给状态添加自定义数据:
$stateProvider.state('name',{})中的.state第二个参数对象可以添加自定义的属性和值,为了避免冲突,一般使用data属性来为它添加自定义属性.
自定义的属性可以通过$state.current.data来访问到.app.config(function ($stateProvider, $urlRouterProvider) { //1.使用路由状态传递参数 //2.路由状态的onEnter和onExit回调处理 $stateProvider.state('contacts', { url: '/contacts/:name', templateUrl: function ($stateParams) { return '/template/' + $stateParams.name + '.html' }, data: { data: 1234 }, controller: function ($scope, $state) { //获取路由状态的参数 // console.info($state.current.data); $scope.data1 = $state.current.data; }, resolve: { title: function () { return 'contacts'; } }, onEnter: function (title) { console.log('进入' + title + '状态'); }, onExit: function (title) { console.log('推出' + title + '状态'); } });});状态的onEnter和onExit回调: 状态的onEnter属性和onExit属性可以用来定义进入状态和退出状态所执行的回调: 注意,回调函数中可以注入resolve里定义的依赖,比如下面的'title': 状态改变事件:
这些事件都是在$rootScope上触发的.测试证明在$scope中绑定也是管用的
$stateChangeStart: 当状态开始改变时触发, 接受5个参数:视图加载事件:
$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事件简单实例:
js:AngularJS Home Page Ui-router Test
点击连接后内容被加载咋爱这里
var app = angular.module('myApp', ['ui.router']);app.config(function ($stateProvider, $urlRouterProvider) { //1.使用路由状态传递参数 //2.路由状态的onEnter和onExit回调处理 $stateProvider.state('contacts', { url: '/contacts/:name', templateUrl: function ($stateParams) { return '/template/' + $stateParams.name + '.html' }, data: { data: 1234 }, controller: function ($scope, $state) { //获取路由状态的参数 // console.info($state.current.data); $scope.data1 = $state.current.data; } });});//注册指令app.directive('loading', function ($rootScope) { return { restrict: 'EA', link: function (scope, iEle, iAttrs, ctrl) { console.log(scope == $rootScope); //状态事件 scope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) { console.log('状态开始改变'); /*toState是定义.state时传入的第二个参数对象*/ console.info(toState); /*toParams就是$stateParams*/ console.info(toParams); /*fromState是上一个状态.state时传入的第二个参数对象*/ console.info(fromState); /*fromParams就是上一个状态的$stateParams*/ console.log(fromParams); if (toParams.name == 'stop') { alert('阻止页面'); event.preventDefault(); } }); scope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { console.log('状态改变结束'); /*参数同上*/ }); scope.$on('$stateNotFound', function (event, unfoundState, fromState, fromParams) { console.log('没有找到对应的状态'); /*unfoundState包含了三个属性:*/ /*1.to:前往的状态名(也就是没有找到的这个状态名) * 2.toParams:前往的状态的参数(在使用ui-sref或者$state.go()的时候可以传入,这个例子里就是{a:1,b:2}) * 3.options:使用$state.go()的时候传入的第三个参数. * */ /*最后两个参数同上*/ console.log(unfoundState); //如果不写这句,那么接下来就会报错,卡住js进程了. event.preventDefault() }); scope.$on('$stateChangeError', function (event, toState, toParams, fromState, fromParams, error) { console.log('切换状态出错'); /*error是一个包含了错误信息的对象*/ console.info(error); }); //视图事件 scope.$on('$viewContentLoading', function (event, viewConfig) { console.log('视图开始加载'); }); scope.$on('$viewContentLoaded', function (event) { console.log('视图渲染完毕'); }); } }});
博文内容来源: