【问题标题】:When does the digest get triggered in AngularJS什么时候在 AngularJS 中触发摘要
【发布时间】:2015-05-14 23:35:47
【问题描述】:

全部:

我有一个关于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:更改名称")

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

谢谢

【问题讨论】:

标签: angularjs digest


【解决方案1】:

我想更正 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 更新为最新更改之后,这有时会很有用。

【讨论】:

  • 是的,你的猜测是正确的,这并不是 AngularJS 特有的,而是 Javascript 的东西。通常,如果您想在当前“执行堆栈”之后执行代码,我们使用setTimeout
  • 谢谢,你能帮忙解决另一个问题吗:stackoverflow.com/questions/30243804/…
  • 我建议的唯一改变是关于简化版本,它真的更像 try { $scope.changename(); } finally { $rootScope.$digest(); } 。即使函数中存在错误,您也会收到 $digest
  • 对@DRobinson,但我更喜欢保留对于这个特定问题最简单的方法,如果人们想知道什么是消化循环或scope.$digest 之间有什么区别,他们会在其他地方找到更好的解释和scope.$apply。但感谢您的精确
  • 当然,因此我添加评论而不是编辑您的答案。我认为没有必要改变你的答案,但希望它出现在 cmets 中,以防有人疯狂地想到“如果我强迫它失败......”
【解决方案2】:

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

【讨论】:

  • 谢谢,我会测试一下。
【解决方案3】:

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

因此,在changename() 中更改name 多少次都没关系;下一个摘要循环只会“看到”最后分配的值。

【讨论】:

  • 谢谢,我要找的关键答案是摘要何时开始,所以根据你的说法,它是在 ng-click 功能完成后开始的,基本上,你证实了我的猜测,对吧?
  • @Kuan 在这种特殊情况下,是的。但你不必猜测这些东西。如有疑问,请查看 Angular 的源代码。我这样做是为了回答你的问题。 :)
  • 感谢您的建议,我是入门级的。所以我想我不是那么喜欢阅读源代码。
猜你喜欢
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-25
  • 1970-01-01
  • 2016-05-20
  • 2017-05-09
相关资源
最近更新 更多