无法渲染模型的属性

时间:2015-06-16 17:48:48

标签: javascript angularjs

向Angular寻求帮助。 有些人,当它的值改变时,无法刷新属性(timerValue)。它确实渲染一次。

这是html div:

<div>{{ game.timerValue }}</div>

js:

// Game status
$scope.game = {
    "started"    : false,
    "timerValue" : 60,
    "score"      : 0,
    "question"   : "? ? ?",
    "message"    : "If all options are set up, then you may start!",
    "wrong"      : ""
  };
 // Handle Start Button click
  $scope.startGame = function () {    

    if($scope.game.timer) clearTimeout($scope.game.timer);

    $scope.game.score = 0;
    $scope.game.wrong = "";    
    $scope.game.message = "The game started!";

    $scope.game.timer = setInterval(function() {      
      $scope.game.timerValue -= 1;
      if( $scope.game.timerValue <= 0)
      {
        $scope.game.message = "Defeat! Time is out! Your score is " + $scope.game.score;
        clearTimeout($scope.game.timer);
      }
    },1000);
  };

没有想法,谢谢你的帮助。

更新:该属性已更改,计时器正在运行。它并不令人耳目一新。

5 个答案:

答案 0 :(得分:3)

您的UI未更新的原因是您的游戏计时器逻辑在常规Angular摘要周期之外运行。有一篇很好的文章解释它:$watch How the $apply Runs a $digest

使用Angular&#39; $interval service而不是setInterval推荐。它是window.setInterval的包装器,让您无需手动调用$scope.$apply或&#34;告诉Angular更新UI&#34;。

使用$interval的其他好处:

  
      
  • 它会在try / catch块中自动包装你的回调,让你处理$exceptionHandler service中的错误。

  •   
  • 它返回一个promise,因此与传统的回调方法相比,它可以更好地与其他基于promise的代码进行互操作。当您的回调返回时,返回的值用于解决承诺。

  •   

另一种解决方案是在setInterval内明确调用$scope.$apply()以通知Angular模型数据已更改,更新UI&#34;。

答案 1 :(得分:0)

setInterval在一个单独的线程(有点)中工作,因此Angular无法检测到它所做的属性的任何更改。您必须使用$scope.$apply(function () {...包装任何修改属性的函数,以便Angular检测它们并将这些更改推送到UI。

答案 2 :(得分:0)

$ scope。$ apply();

工作JS Bin

$scope.game.timer = setInterval(function() {      
      $scope.game.timerValue -= 1;
      if( $scope.game.timerValue <= 0)
      {
        $scope.game.message = "Defeat! Time is out! Your score is " + $scope.game.score;
        clearTimeout($scope.game.timer);
      }
      $scope.$apply();
    },1000);

答案 3 :(得分:0)

您可以在每个间隔结束时执行$scope.$apply()以获得您想要达到的效果。如果你试图在这个函数内部(如果你要扩展它)或者在外面,如果你要扩展调用它的函数,那么只要警惕confilicts。

您还可以执行@Discosultan建议并使用$scope.$apply()的内容,$interval应该会在每个间隔结束时自动将范围内的更改应用于范围,如果您使用$scope.$apply(),则不会产生冲突代码中的其他地方。通过使用$interval,它将成为您的摘要周期的一部分,并且您希望确保不会在摘要循环中放入大量计算繁重的代码,否则可能会降低整个应用程序的速度,如下面的注释所述@AlvinThompson

答案 4 :(得分:0)

使用Angular(setInterval)之外的函数进行刷新。要告诉角度在视图中应用更改,您有两个解决方案: 使用$scope.$apply()

$scope.startGame = function () {    

    if($scope.game.timer) clearTimeout($scope.game.timer);

    $scope.game.score = 0;
    $scope.game.wrong = "";    
    $scope.game.message = "The game started!";

    $scope.game.timer = setInterval(function() {      
      $scope.game.timerValue -= 1;
      $scope.$apply();

      if( $scope.game.timerValue <= 0)
      {
        $scope.game.message = "Defeat! Time is out! Your score is " + $scope.game.score;
        clearTimeout($scope.game.timer);
      }
    },1000);
  };

或使用$timeout

$scope.startGame = function () {    

    if($scope.game.timer) $timeout.cancel($scope.game.timer);

    $scope.game.score = 0;
    $scope.game.wrong = "";    
    $scope.game.message = "The game started!";

    $scope.game.timer = $timeout(function() {      
      $scope.game.timerValue -= 1;

      if( $scope.game.timerValue <= 0)
      {
        $scope.game.message = "Defeat! Time is out! Your score is " + $scope.game.score;
        $timeout.cancel($scope.game.timer);
      }
    },1000);
  };

不要忘记在控制器依赖项中注入$timeout