AngularJS Controller之间的通信

在AngularJS中我们可以通过其事件系统完成Controller之间的通信。

AngularJS事件系统基于发布/订阅者模式 ,我们可以通过$scope对应的$on方法订阅事件。用$broadcast``$emit发布事件。

$broadcast是自上而下的广播,当前$scope发布事件后所有其后代$scope都可以对事件作出响应。

$emit是从下向上发射出的事件,当前$scope发布事件只有它的祖先$scope可以对事件作出响应,并且任一祖先$scope都可以终结事件,阻止事件继续冒泡。

Angular为每个controller分配一个独立的$scope,controller之间的关系也对应着$scope之间的关系

$broadcast $emit $on 使用

我们创建了三个controller:grandCtrparentCtrchildCtr。grandCtr和parentCtr订阅了childCtr发布的事件,childCtr订阅了parentCtr发布的事件。

  • 事件的命名建议加上特定的前缀,因为事件可能跨函数乃至跨文件,避免混淆。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
	</head>
	<body>
		<div ng-app="app">
			<div ng-controller="grandCtr">
				<div ng-controller="parentCtr">
					Parent name :
					<input ng-model="name" type="text" ng-change="send();" />
					<div ng-controller="childCtr">Child name :
						<input ng-model="name" type="text" ng-change="send();" />
					</div>
				</div>
			</div>
			<script>
				angular.module("app", []).controller("grandCtr", function($scope) {
					$scope.$on("event_childName",
						function(event, msg) {
							console.log("Grand Receive:", msg);
						});

				}).controller("parentCtr", function($scope) {

					$scope.name = "chenjy";

					$scope.send = function() {
						$scope.$broadcast("event_parentName", $scope.name);
					}
					$scope.$on("event_childName",
						function(event, msg) {
							console.log("Parent Receive:", msg);
						});

				}).controller("childCtr", function($scope) {

					$scope.name = "tom";

					$scope.send = function() {
						$scope.$emit("event_childName", $scope.name);
					}
					$scope.$on("event_parentName",
						function(event, msg) {
							console.log("Child Receive:", msg);
						});
				});
			</script>
	</body>
</html>

我们也可以在parentCtr终止事件的继续传播。


.controller("parentCtr", function($scope) {

					$scope.name = "chenjy";

					$scope.send = function() {
						$scope.$broadcast("event_parentName", $scope.name);
					}
					$scope.$on("event_childName",
						function(event, msg) {
							console.log("Parent Receive:", msg);
							// 阻止事件继续传播
				            event.preventDefault();
				            event.stopPropagation();
						});

				})

$rootScope.$emit 和 $rootScope.$on()

$rootScope是所有$scope的最顶层的祖先。所以我们可以通过将事件发布在$rootScope$rootScope.$emit,然后直接在$rootScope订阅事件。

这样比较高效的方式,因为$rootScope已经是最顶层祖先不会继续冒泡,而且其他scope对此一无所知。

但是$rootScope.$broadcast+ $scope.$on却是很浪费性能的方式,事件会从最顶层开始逐层传播

事件清除

使用$rootScope.$emit 和 $rootScope.$on()我们可以很快速 高效的发布/订阅事件,但是由于事件是发布在$rootScope上面的。当我们的子scope
销毁时事件并不会被清除。所以我们需要手动清除在$rootScope上面发布的事件。

AngularJS并没有手动退订的事件。在我们订阅事件的时候会返回一个退订函数。我们只需要在需要退订的时候调用该函数即可


<body>
		<div ng-app="app">
				<div ng-controller="parentCtr">
					Parent name :
					<input ng-model="name" type="text" ng-change="send();" />
					<button ng-click="desub()">Unsub</button>
					<div ng-controller="childCtr">Child&nbsp;&nbsp; name :
						<input ng-model="name" type="text" ng-change="send();" />
					</div>
				</div>
			<script>
				angular.module("app", []).controller("parentCtr", ["$scope","$rootScope",function($scope,$rootScope) {
                    
                     var sub = $rootScope.$on("event_childName",
						function(event, msg) {
							console.log("Parent Receive:", msg);
						});
                    
					$scope.name = "chenjy";

					$scope.send = function() {
						$scope.$broadcast("event_parentName", $scope.name);
					}
					
					$scope.desub = function(){
						sub();
					}
				}]).controller("childCtr", ["$scope","$rootScope",function($scope,$rootScope) {

					$scope.name = "tom";

					$scope.send = function() {
						$rootScope.$emit("event_childName", $scope.name);
					}
					$scope.$on("event_parentName",
						function(event, msg) {
							console.log("Child Receive:", msg);
						});

				}]);
			</script>
	</body>

posted @ 2018-10-22 19:57  可爱的黑精灵  阅读(689)  评论(0编辑  收藏  举报