更改变量后的Angular $ watch函数

时间:2016-06-06 14:23:19

标签: angularjs watch

我正在尝试构建一个延迟的消息框。我发现应用程序启动时会调用apply,如API文档中所述。但是当观察到的值发生变化时,它就不会被调用。 MessageCtrl是内部控制器。更改watch var?

后,为什么message被调用
angular.module('myApp',[]).controller('MessageCtrl', function($scope) {

  $scope.getMessage = function() {
    setTimeout(function() {
      $scope.$parent.message = {text : ""}; 
      $scope.$apply(function() {        
        console.log('message:' + $scope.$parent.message.text);
      });
    }, 2000);
  }
  $scope.getMessage();    
})
.controller('MainCtrl',function($scope){
  $scope.message={text:"oi"};
  $scope.$watch("message", function(newValue, oldValue){
      console.log("watch " + $scope.message.text);
  });
});

内部控制器MessageCtrl将收到短信并显示2秒钟。

<body ng-app="myApp" ng-controller="MainCtrl">
  <div ng-controller="MessageCtrl">
    Message:{{message.text}} 
  </div>
</body>

3 个答案:

答案 0 :(得分:2)

据我所知,您的代码确实有效。但是,您正在使用$apply错误。 $apply让你通知angular你正在改变通常方法之外的状态,因此应该重新评估绑定等。所以你应该使用

$scope.$apply(function() { $scope.$parent.message = {text: 'new message'}; });

angular.module('myApp', []).controller('MessageCtrl', function($scope) {

    $scope.getMessage = function() {
      setTimeout(function() {
        $scope.$apply(function() {
          $scope.$parent.message = {
            text: "new message"
          };
          console.log('message:' + $scope.$parent.message.text);
        });
      }, 2000);
    }
    $scope.getMessage();
  })
  .controller('MainCtrl', function($scope) {
    $scope.message = {
      text: "oi"
    };
    $scope.$watch("message", function(newValue, oldValue) {
      console.log("watch " + $scope.message.text);
    });
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp" ng-controller="MainCtrl">
  <div ng-controller="MessageCtrl">
    Message:{{message.text}}
  </div>
</div>

有一点需要注意的是,您应该使用角度$timeout服务,它允许您在应用中设置超时,但您不必处理调用$ apply。

angular.module('myApp', []).controller('MessageCtrl', function($scope, $timeout) {

    $scope.getMessage = function() {
      $timeout(function() {
        $scope.$parent.message = {
          text: "new message"
        };
        console.log('message:' + $scope.$parent.message.text);
      }, 2000);
    }
    $scope.getMessage();
  })
  .controller('MainCtrl', function($scope) {
    $scope.message = {
      text: "oi"
    };
    $scope.$watch("message", function(newValue, oldValue) {
      console.log("watch " + $scope.message.text);
    });
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp" ng-controller="MainCtrl">
  <div ng-controller="MessageCtrl">
    Message:{{message.text}}
  </div>
</div>

答案 1 :(得分:1)

您需要使用$scope.apply方法,因为setTimeout函数不是角度原生函数:

    setTimeout(function() { 
$scope.apply({
$scope.$parent.message = {text : ""}; $scope.$apply(function() { console.log('message:' + $scope.$parent.message.text); });}) ;}, 2000);

或者您也可以使用角色内的$timeout内置服务:

angular.module('myApp',[]).controller('MessageCtrl', function($scope, , $timeout) { $scope.getMessage = function() { $, $timeout(function() { $scope.$parent.message = {text : ""}; $scope.$apply(function() { console.log('message:' + $scope.$parent.message.text); }); }, 2000); } $scope.getMessage(); })

答案 2 :(得分:0)

使用$timeout代替执行$apply

$apply implicity
angular.module('myApp',[]).controller('MessageCtrl', function($scope, $timeout) {
$scope.getMessage = function() {
   $timeout(function() {
      $scope.$parent.message = {text : ""}; 
      $scope.$apply(function() {        
        console.log('message:' + $scope.$parent.message.text);
      });
    }, 2000);
  }
  $scope.getMessage();    
})