为什么指令的子节点无法读取其指令的范围?

时间:2014-12-01 20:03:26

标签: javascript angularjs angularjs-scope angular-directive

我对angularjs指令中的范围有疑问。请查看以下代码:

HTML:

<div ng-controller="MyCtrl">
<!-- 1. works: -->
<pre>{{controllerItems}}</pre>


<my-list attr-items="controllerItems">

  <!-- 3. works not: -->
  <pre>{{directiveItems}}</pre>

  <!-- 4. works: -->
  <pre>{{controllerItems}}</pre>
</my-list>
</div>

JS:

angular.module('myapp', [])

.controller('MyCtrl', function($scope) {
    $scope.controllerItems = [
        'A', 'B', 'C', 'D'    
    ];
})

.directive('myList', function () {
    return {
      restrict: 'E',
      transclude : true,
      template : '<!-- 2. works: --><pre>{{directiveItems}}</pre><div ng-transclude></div>',
      scope : {
        directiveItems : '=attrItems'
      },
      link: function (scope, element, attrs, ctrl) {
        //console.log(scope);
      }
    }
}); 

我尝试做的是为指令及其所有子节点创建自己的作用域。我使用范围:{} 创建了一个新的指令范围,并且期望该指令的所有子节点都可以使用它。但我得到的是, 3。不知道 directiveItems ,并且在 4。中,父作用域仍然存在。

我的问题:如何使用指令创建单独的作用域,该指令也适用于所有子元素,如{{}}或其他默认元素和自定义元素?

您还可以在此处找到代码:http://plnkr.co/edit/kKtGdNt8Jq09zabwVoJo?p=preview

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

模板中使用的ng-transclude指令将已转换的内容绑定到原型继承父作用域的新作用域(通过作用域。$ new())。因此,这个新范围可以看到controllerItems和隔离范围变量directiveItems不可用。

如果要将已转换的内容绑定到隔离范围,请使用传递给链接函数的transcludeFn并将隔离范围传递给它。请注意,执行此操作时,controllerItems将不再可用:

.directive('myList', function () {
    return {
      restrict: 'E',
      transclude : true,
      template : '<pre>{{directiveItems}}</pre>',
      scope : {
        directiveItems : '=attrItems'
      },
      link: function (scope, element, attrs, ctrl, transcludeFn) {
         //Bind the transcluded content to the isolated scope
         transcludeFn(scope, function (clone) {
            element.after(clone);
         }
      }
    }
}); 

http://jsfiddle.net/vjxn7qyc/1/

谨慎地使用它,因为隔离范围应该这样做,将自己与外部代码隔离开来。当您转换声称知道隔离范围的内容时,您正在弯曲规则:)。