角度监视器和事件监听器以什么顺序执行?

时间:2015-12-29 21:02:03

标签: javascript angularjs angular-digest

如果首先更改范围属性,然后再广播事件,那么相应的观察者回调和事件监听器回调是否始终以相同的顺序执行?例如:

$scope.foo = 3;
$scope.$broadcast('bar');

和其他地方:

$scope.$watch('foo', function fn1(){...});
$scope.$on('bar', function fn2(){...});

fn1总是会fn2之前执行,反之亦然,或者订单是否可以依赖?请引用消息来源,最好是官方角度文档。

如果重要:让我们假设$ scope.foo =并且$ broadcast出现在由ng-click调用的函数中(即用户交互)

[旁边]抱歉问题标题很草率 - 如果你有更好的东西请重命名。

1 个答案:

答案 0 :(得分:5)

要了解正在发生的事情,您需要了解Angular的$digest周期和事件$emit and $broadcast函数。

根据一些研究,我也学会了Angular does not use any kind of polling mechanism to periodically check for model changes。这在Angular文档中没有解释,但可以进行测试(参见this answer to a similar question)。

把所有这些放在一起,我写了a simple experiment并得出结论,你可以依靠首先运行的事件处理程序,然后依靠你的监视功能。这是有道理的,因为在摘要循环期间可以连续多次调用监视功能。

以下代码......

<强> template.html

<div ng-app="myApp">
  <div watch-foo ng-controller="FooController">
    <button ng-click="changeFoo()">
      Change
    </button>
  </div>
</div>

<强>的script.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/

在所有情况下,您都可以依赖在监视功能之前调用的事件侦听器。