在AngularJS指令中使用单向绑定

时间:2014-08-12 11:47:39

标签: javascript angularjs

我有一个如下定义的指令:

myApp.directive('stoplight', function() {
    return {
        restrict:'E',
        transclude: true,
        scope: {
            value: '@'
        }, 
        link: function(scope, element) {
            if (scope.value === true) {
                element.html('<i class="icon icon-true green"></i>');
            } else if (scope.value === false) {
                element.html('<i class="icon icon-false red"></i>');
            } else {
                element.html('<i class="icon icon-unknown yellow"></i>');
            }
        }
    };
});

当我使用此指令时,我使用以下标记:

<stoplight value="boolValue" />

我在冷光灯后面的控制器看起来像这样:

myApp.controller('MyController', function($scope, $http) {
    $scope.boolValue = null;
    $scope.init = function() {
      $scope.boolValue = false;
      $http.jsonp('http://anyorigin.com/get?url=www.google.com&callback=JSON_CALLBACK')
        .success(function() {
            console.log('woohoo!');
            $scope.boolValue = true;
        });
    };

    $scope.init();
}};

我有两个问题,对我来说都没有意义。

  1. 我的指令中的“@”不起作用。如果我将“@”更改为“=”,则链接功能会按预期运行。但是,出于性能原因,我想使用单向绑定而不是双绑定。
  2. 由于某种原因,我成功回调中的$scope.boolValue = true;不会更新UI。图标保持红色。我可以将值设置为null,期望黄色,但它保持红色。如果我查看控制台窗口,我可以看到“woohoo!”。我不明白为什么在回调之外更新boolValue有效,但在回调中,它只是不起作用。我在控制台窗口或其他任何性质上都没有看到任何错误。
  3. 有人可以帮我确定一下为什么这不起作用?我不确定这是一个问题还是两个问题。我认为他们都与绑定有关。但是,我不确定如何解决这个问题。

    谢谢。

3 个答案:

答案 0 :(得分:1)

关于问题#1,我相信它正在发生,因为'@'总是会产生一个字符串值。所以你可能需要scope.value ==='true'和scope.value ==='false'。

关于问题#2,正如neilhem已经回答的那样,你需要双花括号:

<stoplight value="{{boolValue}}" />

答案 1 :(得分:0)

使用双花括号<stoplight value="{{ boolValue }}" />

答案 2 :(得分:0)

对于#1:使用@并不意味着'单向绑定',它意味着获取DOM属性的评估值,而不是变量,因此scope.value将导致字符串值'boolValue ',您可以在模板中使用<stoplight value="{{ boolValue }}" />或在指令中使用=Here is a great explanation how @ and = differs.

对于#2:您的UI不会更新,因为您的指令不会监视属性值的更改。初始化指令时,它会获取第一个值并执行指令中的内容 - 但就是这样。当值发生变化时,指令中不会发生任何事情。试试这个:

myApp.directive('stoplight', function() {
  return {
    restrict:'E',
    transclude: true,
    scope: {
      value: '@'
    },
    link: function(scope, element) {
      scope.$watch(function() { return scope.value; }, function(value) {
        if (value === true) {
          element.html('<i class="icon icon-true green"></i>');
        } else if (value === false) {
          element.html('<i class="icon icon-false red"></i>');
        } else {
          element.html('<i class="icon icon-unknown yellow"></i>');
        }
      });
    }
  };
});