AngularJs指令 - 属性作用域变量不绑定

时间:2014-01-23 14:12:07

标签: javascript angularjs

随附plunker(在coffeescript中,但下面是javascript)

我无法在指令中获取属性范围的变量(@)。

这是指令代码:

app.directive('myDirective', [
  function() {

    var compileFn, config, linkFn;

    linkFn = function($scope, element, attr) {
      return alert("foo: " + $scope.foo);
    };

    compileFn = function() {
      return linkFn;
    };

    return config = {
      compile: compileFn,
      scope: {
        foo: '@myDirectiveFoo'
      }
    };
  }
]);

和HTML:

<span my-directive my-directive-foo="bar"></span>

我希望被警告的值是'bar',但它是未定义的。我错过了什么?

1 个答案:

答案 0 :(得分:7)

简短回答:要在foo函数中获得预期值link,您必须观察属性:

attr.$observer('myDirectiveFoo', function(value){
    console.log(value);
    console.log($scope.foo);
});

两个控制台输出都会为您提供预期的bar值。为什么?必须插入属性值,这将在调用链接函数后发生。

长答案:为传递给链接函数的attr对象声明的文档:

  

使用$ observe观察包含插值的属性的值变化(例如src =“{{bar}}”)。这不仅非常有效,而且它也是轻松获得实际值的唯一方法,因为在链接阶段,插值尚未进行评估,因此此时的值设置为未定义。

让我们来看看你的例子的修改版本。它还显示了=@范围界定之间的差异。

这是我们的HTML:

<body ng-controller="MainCtrl">
   <span  my-directive my-directive-foo="hello {{name}}" my-directive-bar="name" ></span>
 </body>

这是控制器:

app.controller('MainCtrl', function($scope, $timeout, $interpolate){
  $scope.name = 'roy';
  $timeout(function(){
    $scope.name = 'michael';
  },4000);
});

如您所见,我们有一个name属性,会在4秒后从 roy 更改为 michael

这是指令:

app.directive('myDirective', function() {
    return {
      scope: {
        foo: '@myDirectiveFoo',
        bar: '=myDirectiveBar'
      },
      link: function ($scope, iElement, iAttrs, controller) {
          console.log('link foo: '+$scope.foo); 
          console.log('link bar: '+$scope.bar);
          iAttrs.$observe('myDirectiveFoo',function(value){
              console.log('link observed foo: '+$scope.foo, value);    
          }); 
          $scope.$watch('bar', function(newValue, oldValue){
              console.log('watch', oldValue, newValue);
          });
          console.log('link done'); 
      },
      controller: function($scope){ 
          console.log('controller foo:'+$scope.foo);
          console.log('controller bar:'+$scope.bar);
      }
  };
});

我们有两个独立的范围属性。 foo配置为单向绑定,bar配置为双向绑定。在控制器输出中,我们将看到双向绑定($ scope.bar)立即可用,而单向绑定($ scope.foo)则不可用。在链接功能中,我们有相同的结果。如果链接完成,我们将看到观察者和观察者将使用当前(和预期)值进行激活。如果name属性在4秒后改变其值,则观察者和观察者将再次触发。

直播@ kbd> PLUNKR