作用域的一个很棒的特点是具有在作用域层次结构内发出和广播事件的能力。事件允许你发送通知给该作用域内不同的层次,告诉它们事件已发生。事件可以是你选择的任何东西,例如值改变或达到阀值。这在许多情况下非常有用,如让子作用域知道一个值已在父作用域中发生变化,反之亦然。
要从作用域发出一个事件,可以使用 $emit()
方法。该方法沿着父作用域层次向上发送一个事件。任何已注册该事件的祖先作用域都会收到通知。 $emit()
方法使用下面的语法:
$scope.$emit(name, [args, ...])
其中 name
是事件名称,而 args
是传递给事件处理函数的零个或多个参数。
使用 $broadcast()
方法把一个事件广播给下方的子作用域层次。任何已注册该事件的后代作用域都会收到通知。$broadcast()
方法使用下面的语法:
$scope.$broadcast(name, [args, ...])
其中 name
是事件名称,而 args
是传递给事件处理函数的零个或多个参数。
要处理发出或广播的事件,可以使用 $on()
方法。$on()
方法使用下面的语法:
$scope.$on(name, listener)
其中 name
是要监听的事件名称,listener
是一个函数,它可以接受事件(event)作为第一个参数,并把由 $emit()
方法或 $broadcast()
方法传递的任何参数作为后续的参数。event
对象具有以下属性:
- targetScope:
$emit()
或$broadcast()
被调用时所在的作用域 - currentScope:当前正在处理该事件的作用域
- name:事件的名称
- stopPropagation():停止在作用域层次结构中向上或向下传播事件
- preventDefault():防止浏览器事件中的默认行为,而只执行自己的自定义函数
- defaultPrevented:一个布尔值,如果 preventDefault() 被调用,则为 true
环境版本:
- AngularJS v1.5.8
一个简单的页面(events.html
):
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>AngularJS Scope Events</title>
<style type="text/css">
div {
padding: 5px;
font: 18px bold;
}
span {
padding: 3px;
margin: 12px;
border: 5px ridge;
cursor: pointer;
}
label {
padding: 2px;
margin: 5px;
font: 15px bold;
}
p {
padding-left: 22px;
margin: 5px;
}
</style>
</head>
<body>
<div ng-controller="firstCtrl">
<span ng-repeat="name in names" ng-click="changeName()">
{{name}}
</span>
<div ng-controller="secondCtrl">
<hr>
<label>Name:</label>
<p>{{currentName}}</p>
<label>Race:</label>
<p>{{currentInfo.race}}</p>
<label>Weapon:</label>
<p>{{currentInfo.weapon}}</p>
<span ng-click="del()">Delete</span>
</div>
</div>
<script type="text/javascript" src="lib/angular.js"></script>
<script type="text/javascript" src="events.js"></script>
</body>
</html>
事件处理(events.js
):
(function() {
angular.module('myApp', [])
.controller('firstCtrl', ['$scope', function($scope) {
$scope.names = ['Frodo', 'Aragorn', 'Legolas', 'Gimli'];
$scope.currentName = $scope.names[0];
$scope.changeName = function() {
// 使用 this 关键字来访问 name 属性
// name 属性实际上来自于被创建的一个动态子作用域
$scope.currentName = this.name;
$scope.$broadcast('change', this.name);
};
$scope.$on('delete', function(event, name) {
var i = $scope.names.indexOf(name);
$scope.names.splice(i, 1);
$scope.currentName = $scope.names[0];
$scope.$broadcast('change', $scope.currentName);
});
}])
.controller('secondCtrl', ['$scope', function($scope) {
$scope.info = {
'Frodo': { weapon: 'String', race: 'Hobbit' },
'Aragorn': { weapon: 'Sword', race: 'Man' },
'Legolas': { weapon: 'Bow', race: 'Elf' },
'Gimli': { weapon: 'Axe', race: 'Dwarf' }
};
$scope.currentInfo = $scope.info['Frodo'];
$scope.$on('change', function(event, name) {
$scope.currentInfo = $scope.info[name];
});
$scope.del = function() {
delete $scope.info[$scope.currentName];
$scope.$emit('delete', $scope.currentName);
};
}]);
})();
对上面代码中 this.name
的解释:
动态子作用域