AngularJS的作用域整数没有在模板上更新



我有一个非常简单的模板:

{{ polygonDotsCount }}

控制器上的代码:

$scope.polygonDotsCount = 0;
$scope.polygonClick = function() {
    $scope.polygonDotsCount = $scope.polygonDotsCount + 1;
    console.log($scope.polygonDotsCount);
};

polygonClick每次点击地图时都会被调用,我看到控制台的数字在增加,但模板上的数字没有增加!这有什么问题吗?

当你在google地图事件的点击上更新范围变量polygonDotsCount时,代码将运行,但改变的范围变量永远不会在html上更新。因为消化循环没有进行。为了更新所有绑定摘要周期必须有。如果你在angular上下文中做任何操作,将正确地应用digest cycle &将更新html上的绑定。但是当你运行任何事件,比如onclick或者外部事件,比如你使用谷歌地图的事件,它们永远不会运行文摘循环。在这种情况下,您需要手动运行它。

何时运行$apply

要手动运行摘要循环,您需要调用scope$apply()方法,该方法将运行$digest()方法并更新所有绑定。但是直接调用$apply()来运行digest循环会导致问题,因为有时它会在运行消化循环时发生。如果当前已经有一个digest cycle正在运行,那么它将抛出一个错误$digest is already in progress

所以最好使用$timeout

$timeout做什么?

它实际上运行一个digest循环,但它有一个优势。当你在$timeout函数中编写代码时,它将被执行&将运行消化循环。但是在运行消化循环时之前运行的digest正在进行中然后它等待消化循环结束&然后在完成该摘要后执行,它将运行自己的摘要循环。

$scope.polygonDotsCount = 0;
$scope.polygonClick = function() {
    $timeout(function(){ //<-- inject $timeout on controller before using it.
         $scope.polygonDotsCount = $scope.polygonDotsCount + 1;
         console.log($scope.polygonDotsCount);
    });
};

使用$timeout将确保它不会与其他运行消化循环

好吧,这似乎是一个问题,使用不同的非角库。我正在使用谷歌地图和the-di-lab.com/polygon的修改版本

由于某些原因,即使我看到控制台上的作用域正在更新,HTML也没有更新,所以我用这个函数强制更新:

$scope.safeApply = function(fn) {
    var phase = this.$root.$$phase;
    if(phase == '$apply' || phase == '$digest') {
        if(fn && (typeof(fn) === 'function')) {
            fn();
        }
    } else {
        this.$apply(fn);
    }
};

如果有人能给出一个解释为什么会发生这种情况和一个更好的解决方法,我会选择他们的答案。

这个问题与消化循环有关。

如果AngularJS通常将我们的代码包装在$apply()中并开始$digest循环,那么什么时候你需要手动调用$apply()呢?实际上,AngularJS把一件事说得很清楚。它将只考虑那些在AngularJS上下文中完成的模型更改(即,更改模型的代码被封装在$apply()中)。Angular的内置指令已经做到了这一点,这样你对模型所做的任何更改都会反映在视图中。然而,如果你改变了Angular上下文之外的任何模型,那么你需要通过手动调用$apply()来通知Angular这些变化。这就像告诉Angular你正在改变一些模型,它应该触发观察者,这样你的改变才能正确传播。

详情请参考"http://www.sitepoint.com/understanding-angulars-apply-digest/"

最新更新