AngularJS - 解释为什么transcluded范围必须是隔离范围的兄弟

时间:2013-07-07 15:12:49

标签: angularjs angularjs-directive

Angular docs on directives中,有以下段落:

  

但是,隔离范围会产生一个新问题:如果是一个被转换的DOM   小部件隔离范围的子项然后它将无法绑定   任何事情。出于这个原因,被饶恕的范围是一个孩子   原始范围,在窗口小部件为其创建隔离范围之前   局部变量。这使得transcluded和widget隔离范围   兄弟姐妹。

有人可以解释一下为什么“如果一个被转换的DOM是小部件隔离范围的子节点那么它将无法绑定到任何东西”?

2 个答案:

答案 0 :(得分:2)

想象一下你有这样的标记:

<html ng-app="myApp">
  <body>
    <div ng-controller="myController">
      <div ng-repeat="item in items">
        <div my-widget>
          {{item.name}}
        </div>
      </div>
    </div>
  </body>
</html>

设置范围树($ rootScope - &gt;控制器范围 - &gt; ng-repeat范围 - &gt;小部件范围)。现在说你的控制器里面有一些东西:

function myController($scope) {
  $scope.items = [
    {name: 'Stella Artois'},
    {name: 'Red Stripe'}
  ];
}

您可以从范围中读取任意数量级别的值,因为它们使用原型继承相互继承。 {{item}}并不存在于小部件范围中,但它在父级重复范围内存在,因此发现它很好。

如果您使用隔离范围,您将获得一个不会从任何东西继承的全新范围​​。因此,如果my-widget使用scope: {},则范围树看起来更像:

$rootScope
└controller scope
  └ng-repeat scope
widget scope

然后在双重卷曲中,&#34;项目&#34;不明。使用transclusion,您可以将范围设置为兄弟姐妹,如下所示:

$rootScope
└controller scope
  └ng-repeat scope
    └widget contents
widget scope

答案 1 :(得分:1)

提到的另一个微妙之处in this talk是,如果你的被抄送内容的范围是指令的子节点,那么该指令可能会破坏被抄送内容试图在父范围内引用的任何变量。例如:

<body ng-controller="MainCtrl">
<my-directive>{{ name }}</my-directive>
</body>

JS:

app.controller("MainCtrl", function($scope) {
    $scope.name = 'foo';
});

app.directive("myDirective", function() {
    return {
        scope: {},
        transclude: true,
        template: '<span ng-transclude></span>',
        controller: function($scope) {
            $scope.name = 'bar';
        }
    }
});

Transclusion确保指令中的{{name}}引用'foo'而不是'bar'。