AngularJS 指令不更新回调的范围



我正在使用指令来创建AngularJS 1.5中的组件库。因此,我的指令需要有独立的作用域。

我的一些指令有回调,所以你可以传入一个函数来被指令调用。然而,当这个回调被指令调用时,它似乎并没有像我期望的那样完全更新$scope属性的更改。

这是一个显示这种行为的Plunker:http://embed.plnkr.co/Rg15FHtHgCDExxOYNwNa/

代码如下:

<script>
    var app = angular.module('myApp', []);
    app.controller('Controller', ['$scope',function($scope) {
        // initialize the value to something obvious
        $scope.clickersValue = "BEFORE";
        // when this call back is called we would expect the value to be updated by updated by the directive
        $scope.clickersCallback = function() {
        //$scope.$apply(); // $apply is not allowed here
        $scope.clickersValueRightAfterCall = $scope.clickersValue;
        console.log("clickersCallback: scope.clickersValue", $scope.clickersValue);
    };
  }
]);
app.directive('clicker', [function() {
  return {
    restrict: 'EA',
    template: '<div ng-click="clicked()">click me!</div>',
    controller: ['$scope', function($scope) {
      $scope.clicked = function() {
        console.log("you clicked me.");
        $scope.newValue = 'VALID';
        $scope.myUpdate();
      }
    }],
    scope: {
      "newValue": "=",
      "myUpdate": "&"
    }
  };
}]);
</script>

所以当clickercallback被调用clickersValue属性仍然有旧的值。我试过使用$scope。$apply,但当另一个更新发生时,当然不允许。我也尝试使用controller_bind,但得到了相同的效果。

clickersCallback函数内的代码包装到$timeout函数中

$timeout(function() {
    $scope.clickersValueRightAfterCall = $scope.clickersValue;
    console.log("clickersCallback: scope.clickersValue", $scope.clickersValue); 
});

更新砰砰作响

$timeout不会产生像" $digest already in progress "这样的错误,因为$timeout会告诉Angular,在当前循环之后,会有一个超时等待,这样它就能确保在两个循环之间不会发生冲突,从而$timeout的输出会在新的$digest循环中执行。源

Edit 1:正如OP下面所说的,指令的用户不应该在他的回调函数中编写任何"特殊"的代码。

为了实现这种行为,我将$timeout从de controller更改为指令。

控制器回调函数(未更改):

$scope.clickersCallback = function() {
    $scope.clickersValueRightAfterCall = $scope.clickersValue;
    console.log("clickersCallback: scope.clickersValue", $scope.clickersValue);
};

指令代码(在指令注入$timeout):

 $scope.clicked = function() {
     console.log("you clicked me.");
     $scope.newValue = 'VALID';
     $timeout(function() {
         $scope.myUpdate();
     });
 }

更新恰好

最新更新