AngularJS : 带有 ng-repeat 和独立作用域的指令

AngularJS : directive with ng-repeat and isolated scope

我一直在尝试创建一个 指令,它获取元素的 内容并用 ng-repeat 包装它。诀窍是元素内容中的表达式必须与指令的隔离范围链接(所以我不能使用ng-transclude)。

我找到了一个看起来很完美的解决方案: https://github.com/angular/angular.js/issues/7874#issuecomment-46410994 但它不适用于不令人满意的隔离范围,我需要一个隔离范围以避免污染父范围。

在下面的plnkr中,您可以尝试注释第10行,它会起作用。 http://plnkr.co/edit/B72H9Sd5Cs1Qc8GoTRGF

<test>
  <h3>- number: {{item}}</h3>
</test>

app.directive('test', function(){
  return {
    restrict: 'E',
    scope: {}, // try commenting this line
    compile: function compile(tElement, tAttrs, tTransclude) {
      var children = tElement.children();

      var template = angular.element('<div ng-repeat="item in collection"></div>');
      template.append(children);

      tElement.html('');
      tElement.append(template);

      return function(scope, iElement, iAttrs, controller) {
        scope.collection = [1, 2, 3, 4, 5];
      };
    }
  };
});

我想要的是

- number: {{item}}

为每个集合项目重复,并且 {{item}} 表达式与孤立的链接范围。

我不明白这种行为。在我看来,{{item}} 表达式应该链接到指令的范围(通过 ng-repeat)。 相反,它与父范围链接。

有人可以帮我理解并解决这个问题吗?

谢谢。

好吧,试试 this fiddle 我添加了一些东西到:

app.directive('test', function(){
  return {
    restrict: 'E',
    scope: {}, // try commenting this line
    compile: function compile(tElement, tAttrs, tTransclude) {
      var children = tElement.children();

      var template = angular.element('<test2>{{collection}}<div ng-repeat="item in collection" ></div></test2>');
      template.append(children);

      tElement.html('');
      tElement.append(template);

      return function(scope, iElement, iAttrs, controller) {
        scope.collection = [1, 2, 3, 4, 5];
        console.log('test', scope);
      };
    }
  };
});

app.directive('test2', function(){
  return {
    restrict: 'E',
    scope: false,
    link: function($scope) {
      console.log('test2', $scope);
    }
  };
});

基本上,当您向 compile: function compile(tElement, tAttrs, tTransclude) { 中的 DOM 添加内容时,该代码会在链接阶段之前执行(return function(scope, iElement, iAttrs, controller) { 中的代码 运行。

如果您查看两个 console.log 调用,您会发现 test2 发生在 test 之前。

将其与 test 上的独立作用域相结合,最终 test 中的作用域成为 test2 中作用域的子级。违反直觉,我知道,但这是 AngularJS 的 compiling/linking 阶段的工作方式。 因此 collectiontest2 中是 undefined 所以 ng-repeat 与 "repeat" 无关。

如果您删除 scope: {},您基本上是在告诉 test 的范围与 test2 的范围相同(它们是对同一对象的引用),因此 collection 将(最终)在所有指令中定义,包括 ng-repeat.