路由的事件
事件这个词在前端出现的频率真是高,根本拦不住,哪都是.$route服务在路由过程中的每个阶段都会触发不同的事件,可以为这些不同的路由事件设置监听器并做出响应.
一共有4个事件用来监听路由的状态变化: $routeStartChange, $routeChangeSuccess, $routeChangeError, $routeUpdate.
其中最常用的是前两个,这里稍微解释一下.
(1) $routeStartChange
看名字就能猜出来它表示的是路由开始变化的事件,在浏览器地址栏发生变化之前AngularJS会先广播一下这个事件.路由会开始加载所有需要的依赖,模板和resolve部分的内容也会注入.
1
2
3
4
5
6
|
angular.module( 'myApp' , []) .run([ '$rootScope' , '$location' , function ($rootScope, $location){ $rootScope.$on( '$routeChangeStart' , function (evt, next, current){ console.log( 'route begin change' ); }); }]); |
解释一下事件的参数,evt是事件对象,可以从中读取到一些route的信息.next是将要导航到的路由,current是当前的URL.
可以看见在这个时期我们可以做很多有用的事,因为此时仅仅是路由开始变化,对应的内容都还没来得及发生改变.这里我们可进行permission的校验,loading画面的加载,对应路由信息的读取等等.
(2) $routeChangeSuccess
在路由的所有依赖都被注入加载后,AngularJS会对外广播路由跳转成功的事件.
1
2
3
4
5
6
|
angular.module( 'myApp' , []) .run([ '$rootScope' , '$location' , function ($rootScope, $location) { $rootScope.$on( '$routeChangeSuccess' , function (evt, current, previous) { console.log( 'route have already changed' ); }); }]) |
这里也稍微解释下三个参数,evt是AngularJS事件对象,current是当前所处路由,previous是上一个路由.
剩下两个不太常用的事件,大家去看官方API说明吧,这里不介绍了
----------------------------------------------------------------------
- $emit只能向parent controller传递event与data( $emit(name, args) )
- $broadcast只能向child controller传递event与data( $broadcast(name, args) )
- $on用于接收event与data( $on(name, listener) )
本节课程源码:
1
2
3
4
5
6
7
8
9
10
|
< div ng-controller = "ParentCtrl" > <!--父级--> < div ng-controller = "SelfCtrl" > <!--自己--> < a ng-click = "click()" >click me</ a > < div ng-controller = "ChildCtrl" ></ div > <!--子级--> </ div > < div ng-controller = "BroCtrl" ></ div > <!--平级--> </ div > |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
var app = angular.module( 'myApp' , []); app.controller( 'SelfCtrl' , function ($scope) { $scope.click = function () { $scope.$broadcast( 'to-child' , 'child' ); $scope.$emit( 'to-parent' , 'parent' ); } }); app.controller( 'ParentCtrl' , function ($scope) { $scope.$on( 'to-parent' , function (event,data) { console.log( 'ParentCtrl' , data); //父级能得到值 }); $scope.$on( 'to-child' , function (event,data) { console.log( 'ParentCtrl' , data); //子级得不到值 }); }); app.controller( 'ChildCtrl' , function ($scope){ $scope.$on( 'to-child' , function (event,data) { console.log( 'ChildCtrl' , data); //子级能得到值 }); $scope.$on( 'to-parent' , function (event,data) { console.log( 'ChildCtrl' , data); //父级得不到值 }); }); app.controller( 'BroCtrl' , function ($scope){ $scope.$on( 'to-parent' , function (event,data) { console.log( 'BroCtrl' , data); //平级得不到值 }); $scope.$on( 'to-child' , function (event,data) { console.log( 'BroCtrl' , data); //平级得不到值 }); }); |
在$on的方法中的event事件参数,其对象的属性和方法如下
事件属性 | 目的 |
---|---|
event.targetScope | 发出或者传播原始事件的作用域 |
event.currentScope | 目前正在处理的事件的作用域 |
event.name | 事件名称 |
event.stopPropagation() | 一个防止事件进一步传播(冒泡/捕获)的函数(这只适用于使用`$emit`发出的事件) |
event.preventDefault() | 这个方法实际上不会做什么事,但是会设置`defaultPrevented`为true。直到事件监听器的实现者采取行动之前它才会检查`defaultPrevented`的值。 |
event.defaultPrevented | 如果调用了`preventDefault`则为true |
----------------------------------------------------------
父传(
$scope.
$broadcast)子接收($scope.
$on)
angular.module('myApp', [])
.controller('ParentCtrl', ['$scope', function($scope) {
$scope.message = "Child updated from parent controller";
$scope.clickFunction = function() {
$scope.$broadcast('update_parent_controller', $scope.message);
};
}
])
.controller('ChildCtrl', ['$scope', function($scope) {
$scope.message = "Some text in child controller";
$scope.$on("update_parent_controller", function(event, message) {
$scope.message = message;
});
}
]);
Here a plunker for a live demo.
Instead, if it need to send data from the SecondController (child) to the FirstController (parent), it should use the $emit method.
Here the javascript code:子传(
$scope.
$emit)父接收($scope.
$on)
angular.module('myApp', [])
.controller('ParentCtrl', ['$scope', function ($scope) {
$scope.message = "Some text in parent";
$scope.$on("update_parent_controller", function(event, message){
$scope.message = message;
});
}])
.controller('ChildCtrl', ['$scope', function ($scope) {
$scope.clickFunction = function() {
$scope.message = "Parent updated";
$scope.$emit('update_parent_controller', $scope.message);
}
}]);
Here a plunker for a live demo.
Finally, here a little trick where two controller have no parent/child relationship.
It should pass data from one controller through $rootScope and the $broadcast method.
Here the javascript code:兄弟传($rootScope.$broadcast)兄弟接收($rootScope.$on)
angular.module('myApp', [])
.controller('FirstCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
$scope.message = "Clicked!";
$rootScope.clickFunction = function() {
$rootScope.$broadcast("Update", $scope.message);
};
}])
.controller('SecondCtrl', ['$scope','$rootScope', function($scope,$rootScope) {
$scope.message = "Waiting for a click...";
$rootScope.$on("Update", function(event, message) {
$scope.message = message;
});
}]);
Here a plunker for a live demo.
----------------------------------------------------------------------------------
发送消息: $scope.$emit(name, data) 或者 $scope.$broadcast(name, data);
接收消息: $scope.on(name,function(event,data){ });
区别: $emit 广播给父controller $broadcast 广播给子controller
broadcast 是从发送者向他的子scope广播一个事件。
这里就是ParentController发送, ParentController 和 ChildController 会接受到, 而MainController是不会收到的
$emit 广播给父controller,父controller 是可以收到消息
$on 有两个参数function(event,msg) 第一个参数是事件对象,第二个参数是接收到消息信息
var app = angular.module('onBroadcastEvent', ['ng']); app.controller('MainController', function($scope) { $scope.$on('To-MainController', function(event,msg) { console.log('MainController received:' + msg); }); }); app.controller('ParentController', function($scope) { $scope.click = function (msg) { $scope.$emit('To-MainController',msg + ',from ParentController to MainController'); $scope.$broadcast('To-ChildController', msg + ',from ParentController to ChildController'); $scope.$broadcast('To-BrotherController', msg + ',from ParentController to BrotherController'); } }); app.controller('ChildController', function($scope){ $scope.$on('To-ChildController', function(event,msg) { console.log('ChildController received:' + msg); }); }); app.controller('BrotherController', function($scope){ $scope.$on('To-BrotherController', function(event, msg) { console.log('BrotherController received:' + msg); }); });