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

Why are these two updates no reflected in the view?

本文关键字:视图 更新 两个 为什么      更新时间:2023-09-26

我试图了解如何通过控制器正确操纵属性。下面的代码在4秒内执行6次更新。更新2和3没有反映在视图中。为什么会这样,我需要做些什么才能让这些类型的更新影响视图?

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

var app = angular.module('myApp', []);
app.controller('Controller',  function ($scope, $interval) {
    $scope.myValue = "first";
    console.log($scope.myValue);
    setTimeout(function() { 
        $scope.myValue = "second";  // never updates
        console.log($scope.myValue);
        $scope.$emit("my-event", "third"); // never updates
        console.log($scope.myValue);
        $interval(function() {
            $scope.$emit('my-event', "fourth");
        }, 1000, 1);
    }, 1000);
    $interval(function() {
        $scope.myValue = "fifth";
        console.log($scope.myValue);
        $interval(function() {        
            $scope.$emit("my-event", "sixth");
        }, 1000, 1);
    }, 3000, 1);
    $scope.$on('my-event', function (event, arg) {
        $scope.myValue = arg;
        console.log(arg);
    });
});

JSFiddle

使用$timeout而不是setTimeout来选择加入摘要循环。second不会显示,因为消化循环的回合覆盖了myValue的值。

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

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

所以我在原来的问题中显然不够清楚,因为upvoted答案(正确)建议使用$timeout而不是setTimeout,然而,最初的意图是理解为什么更新没有反映在视图中,以及可以做些什么来让这些类型的更新(源自外部角)影响视图。

阅读Scope指南

因此,虽然我选择跳过开发指南的作用域部分,因为它看起来最无聊,但它可能是最重要的,它清楚地指出了理解angular如何绑定数据的一些必要事项,特别是作用域生命周期,其中指出;

当浏览器调用JavaScript时,代码在Angular执行上下文,这意味着Angular不知道模型修改。正确处理模型修改execution必须使用$apply进入Angular的执行上下文方法。只有在$apply内部执行的模型修改

这里有一个很好的答案,可以进一步解释这个概念。第一句话恰当地重申了理解作用域的重要性:

你需要知道Angular是如何工作的才能理解它。

不要只调用$scope.$apply

所以你开始在周围的地方添加对$scope.$apply的调用来满足这些来自外部角的东西,但最终你开始得到:

Error: $digest already in progress

这意味着你不能调用$scope.$apply,而$digest正在执行。在此之后,您可能会想,我如何根据$digest当前是否运行有条件地调用$scope.$apply。但是,你不需要这样做…

直接使用$timeout

哈,就像被点赞的答案一样,我知道,但我认为是基于不同的思维过程。看看这个答案。$timeout不仅仅是用来代替setTimeout,而是用来(没有delay)包装任何从范围生命周期之外调用的模型更新,这样做可以确保不与任何当前处理的$digest冲突。

<标题>结束h1> 所以,在原始代码片段中,第二次和第三次更新没有反映在视图中,因为它们是在Angular执行上下文之外执行的。第三次更新不影响模型的事实也意味着调用执行上下文之外的事件也不会使您进入执行上下文。

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

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);