AngularJS 中什么时候触发摘要

When does the digest get triggered in AngularJS

全部:

我有一个关于 angularjs 数据摘要如何监控范围数据变化的问题,例如:

 <button ng-click="changename()">{{name}}</button>

数据更改函数如下:

            $scope.name = "Change Name";
            $scope.changename = function(){
                $scope.name = "name1";
                $scope.name = "name2";
            }

            $scope.$watch("name", function(newname, oldname){
                if(newname!=oldname){
                    console.log("new: "+newname, "old: "+oldname);
                }
            });

这个changename函数连续改变了scope.name两次,但是观察者只能捕捉到从"Change Name"到"name2"的变化(控制台只打印 "new: name2 old: Change Name")

谁能证实我的猜测摘要循环仅在功能块执行完毕后才开始?

谢谢

是也不是。 JavaScript 是在单线程上执行的,所以会有 2 次调用 $watch 函数,但是只有在 $scope.changename() 完成之后,所以第二次调用会有 newname == oldname == 'name2'.

通常 Angular 在 某些事件发生后 触发摘要循环。在您的情况下, ngClick 指令在执行提供的表达式后触发摘要。对于许多其他用户触发的事件也是如此,例如mouseover, keydown, keypress.

所以在changename()里面改变name多少次都没有关系;下一个摘要周期只会 "see" 最后分配的值。

我想更正 rbaghbanli 的误导性答案。

的确,因为 JavaScript 是单线程的,当你点击那个按钮时会发生什么:

The variable `$scope.name` is set to "name1";
The variable `$scope.name` is set to "name2";
> end of execution stack

Angular runs a $digest cycle
The $watchers are executed
since a watcher value has changed, angular runs another $digest cycle
The $watchers are executed
The watcher have the same value, end of $digest cycle
> end of execution stack

所以当你在同一个函数中时,基本上没有观察者也不会发生任何事情,直到这个函数的每一行结束。

Angular 在您的 changename 调用之后运行摘要循环的原因是因为它在 ng-click 指令中,并且与所有 Angular 内置一样指令,代码实际上包含在 $scope.$apply 调用中。您可以将 ng-click 解读为以下代码(即使从技术上讲它并不完全像这样):

element.on('click', function() {
  $scope.changename();
  $rootScope.$digest();
});

注意:我想简化通用的想法,但从技术上讲,Angular 会在您的代码之后立即执行其 $digest 循环(正如您在我的伪 ng-click 中看到的那样), 在同一个执行堆栈中。这意味着任何 setTimeout 或其他异步调用都将在 之后 摘要周期和 DOM 更新为最新更改后发生,这有时很有用。