要了解发生了什么,您需要了解 Angular 的$digest循环和事件$emit 和 $broadcast函数。
根据一些研究,我还了解到 Angular不使用任何类型的轮询机制来定期检查模型更改。Angular 文档中没有对此进行解释,但可以对其进行测试(请参阅this answer to a similar question)。
把所有这些放在一起,我写了一个简单的实验并得出结论,你可以依靠你的事件处理程序首先运行,然后是你的手表功能。这是有道理的,因为在摘要循环期间可以连续多次调用 watch 函数。
以下代码...
模板.html
<div ng-app="myApp">
<div watch-foo ng-controller="FooController">
<button ng-click="changeFoo()">
Change
</button>
</div>
</div>
脚本.js
angular.module('myApp', [])
.directive('watchFoo', watchFooDirective)
.controller('FooController', FooController);
function watchFooDirective($rootScope) {
return function postLink(scope) {
scope.$watch(function () {
return scope.foo;
}, function (value) {
console.log('scope.$watch A');
});
scope.$on('foo', function (value) {
console.log('scope.$on A');
});
$rootScope.$on('foo', function (value) {
console.log('$rootScope.$on A');
});
$rootScope.$on('foo', function (value) {
console.log('$rootScope.$on B');
});
scope.$on('foo', function (value) {
console.log('scope.$on B');
});
scope.$watch(function () {
return scope.foo;
}, function (value) {
console.log('scope.$watch B');
});
};
}
function FooController($scope) {
$scope.foo = 'foo';
$scope.changeFoo = function() {
$scope.foo = 'bar';
$scope.$emit('foo');
};
}
...单击“更改”按钮时在控制台中产生以下结果:
scope.$on A
scope.$on B
$rootScope.$on A
$rootScope.$on B
scope.$watch A
scope.$watch B
更新
这是另一个测试,说明在摘要循环中调用了两次监视回调,但没有第二次调用事件处理程序:https ://jsfiddle.net/sscovil/ucb17tLa/
第三个测试在 watch 函数中发出一个事件,然后更新被监视的值:https ://jsfiddle.net/sscovil/sx01zv3v/
在所有情况下,您都可以依赖在监视函数之前调用的事件侦听器。