角度观察程序和事件侦听程序的执行顺序

In what order do angular watchers and event listeners execute?

本文关键字:程序 执行 顺序 事件 观察      更新时间:2023-09-26

如果先更改作用域属性,然后再广播事件,那么相应的观察者回调和事件侦听器回调是否总是按相同的顺序执行?例如:

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

和其他地方:

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

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

如果它很重要:让我们假设$scope.foo=和$broadcast发生在通过ng点击(即用户交互)调用的函数中

[旁白]很抱歉题目太草率了——如果你有更好的题目,请重新命名。

要了解正在发生的事情,您需要了解Angular的$digest循环以及事件$emit和$broadcast函数。

基于一些研究,我还了解到Angular不使用任何类型的轮询机制来定期检查模型更改。Angular文档中没有对此进行解释,但可以进行测试(请参阅类似问题的答案)。

综合所有这些,我写了一个简单的实验,得出的结论是,可以先运行事件处理程序,然后运行手表功能。这是有道理的,因为在摘要循环中可以连续多次调用watch函数。

以下代码。。。

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

更新

下面是另一个测试,它说明了在摘要循环中两次调用watch回调,但没有第二次调用事件处理程序:https://jsfiddle.net/sscovil/ucb17tLa/

第三个测试在watch函数内发出一个事件,然后更新被监视的值:https://jsfiddle.net/sscovil/sx01zv3v/

在所有情况下,您都可以依赖于在watch函数之前调用的事件侦听器。