为什么这两个更新没有反映在视图中?

时间:2015-08-07 15:25:34

标签: javascript angularjs angularjs-scope

我正在尝试了解如何通过控制器正确操作属性。以下代码在四秒钟内执行六次更新。更新二和三未反映在视图中。为什么这样,以及如何更新这些类型会影响视图?

HTML

%destructor { free($$); } <str_val>

的Javascript

<div ng-controller="Controller"> 
    myValue: <span ng-bind="myValue"></span>
</div>

JSFiddle

3 个答案:

答案 0 :(得分:4)

使用$timeout代替setTimeout来选择加入摘要周期。自摘要周期结束后,second无法显示myValue的值。

更新了小提琴:https://jsfiddle.net/d9gbpddy/4/

答案 1 :(得分:0)

您可以尝试{{myValue}}而不是<span>元素

答案 2 :(得分:0)

所以我在原始问题中显然不够清楚,因为正确的回答(正确)建议使用$timeout而不是setTimeout,但最初的意图是理解为什么更新未在视图中反映出来,以及如何使这些类型的更新(源于角度之外)会影响视图。

阅读范围指南

因此,虽然我选择跳过开发人员指南的Scopes section因为它看起来最无聊,但它可能是最重要的,它清楚地指出了一些必须要理解角度如何绑定数据的项目,值得注意的是范围生命周期;

  

当浏览器调用JavaScript时,代码在外部执行   角度执行上下文,这意味着Angular不知道   模型修改。要正确处理模型修改   执行必须使用$apply进入Angular执行上下文   方法。仅在$apply内执行的模型修改   方法将由Angular正确解释。

有一个很好的answer here进一步解释了这个概念。第一句恰当地重申了解范围的重要性:

  

您需要了解Angular如何运作才能理解   它

不要只调用$ scope。$ apply

所以你开始在这个地方添加$scope.$apply的调用来迎合那些源于角度以外的东西,但最后你开始得到:

Error: $digest already in progress

这意味着在$scope.$apply正在执行时,您无法调用$digest。之后你可能会想,我怎样才能根据$scope.$apply当前是否正在运行来有条件地调用$digest。但是,你不需要这样做......

只需使用$ timeout

哈,就像upvoted answer一样,我知道,但基于一个不同的思考过程,我认为。见this answer$timeout不只是用来代替setTimeout,而是被用来(没有delay)来包装从Scope Life Cycle之外调用的任何模型更新,并且因此,请确保不会与当前正在处理的任何$digest冲突。

结束

因此,在原始代码段中,第二次和第三次更新不会反映在视图中,因为它们是在Angular执行上下文之外执行的。第三次更新不会影响模型的事实也意味着在执行上下文之外调用事件也不会让您进入执行上下文。

第四个更新已经包含在$interval中,这本身会导致代码在下一个摘要上运行的更新。因此,更新代码以显示角度执行上下文之外的事件示例,该事件导致其更新显示在视图中,如下所示:

setTimeout(function() { 
    $timeout(function({ // start wrap
        $scope.myValue = "second";  // now this updates!
        console.log($scope.myValue);
        $scope.$emit("my-event", "third"); // now this updates!
    })); // end wrap
    console.log($scope.myValue);
    $interval(function() {
        $scope.$emit('my-event', "fourth");
    }, 1000, 1);
}, 1000);