在使用AngularJS中的第三方工具和外部DOM事件时,要记住的一件主要事情是使用$scope.$apply()
方法操作来启动更改。这很了不起,但是有时候我自己的作用域本身已经在消化摘要(这基本上是$ apply方法触发的内容)并在进行这种操作时调用$ apply会引发错误。因此,要解决此问题,每当进行摘要时,您就必须注意$scope.$$phase
标志,该标志设置为作用域。
现在,假设您要更改URL,然后启动:
$scope.$apply(function() {
$location.path('/home');
});
这可以按预期工作,但是现在让我们假设$ scope正在忙着做这件事。因此,您可以检查$$ phase变量,并假设您的更改将被提取:
if($scope.$$phase) {
$location.path('/home');
}
else {
$scope.$apply(function() {
$location.path('/home');
});
}
这就是我一直在做的事情(显然不是在进行代码复制),而且似乎100%的时间都可以工作。我担心的是,当作用域处于消化过程的中间时,AngularJS如何吸收变化?
也许这个例子不够具体。让我们假设更大的东西。想象一下,如果您有一个巨大的网页,其中包含大量的绑定,并假定摘要将线性地浏览整个页面(我假设它在优先级方面做了类似的事情……在这种情况下,首先是DOM树),然后从上到下更新页面上的绑定。
<div class="binding">{{ binding1 }}</div>
<div class="binding">{{ binding2 }}</div>
<div class="binding">{{ binding3 }}</div>
<div class="binding">{{ binding4 }}</div>
<div class="binding">{{ binding5 }}</div>
<div class="binding">{{ binding6 }}</div>
<div class="binding">{{ binding7 }}</div>
<div class="binding">{{ binding8 }}</div>
让我们假设一个消化正在进行,并且它在消化队列的中间附近。现在,让我们尝试在页面顶部某处更改绑定值。
if($scope.$$phase) {
$scope.binding1 = 'henry';
}
现在,以某种方式,AngularJS接受更改并正确更新绑定。即使更改本身可以被认为相对于HTML / DOM在队列中更早发生。
我的问题是AngularJS如何管理这种潜在的竞争状况?如果binding8更新(因为它在页面的下方),我会感到有点自在,但是由于binding1也更新(立即进行,而无需再次调用$ apply),这让我有些迷茫。这是否意味着在其间的某个位置分派了另一个消化?还是$ scope对象比我预期的更神奇?我认为这个问题以前已经解决过,但是由于首先要了解$$ phase和$ scope有点棘手,所以我假设这也可能是一个裂缝。
有任何想法吗?
最佳答案
关于绑定和种族条件。 $ digest将循环所有观察者,直到没有更改为止。您可以通过将日志添加到观察者/绑定方法来观察到,它将至少两次调用每个绑定/观察者,以确保没有更改并且所有绑定值都是稳定的。这些只是脏检查,直到所有值都被解析(在2次循环迭代中都没有改变)之前运行。希望有帮助。
AngularJS文档中对此进行了解释:http://docs.angularjs.org/api/ng.$rootScope.Scope#$digest
注意:这是matsko要求复制/粘贴我的评论。
关于angularjs - $ scope和$$ phase解决方法是否始终能按预期在AngularJS中工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13639717/